diff --git a/libmve/CMakeLists.txt b/libmve/CMakeLists.txt index 5def0543..178cf79c 100644 --- a/libmve/CMakeLists.txt +++ b/libmve/CMakeLists.txt @@ -14,3 +14,8 @@ set(CPPS add_library(libmve STATIC ${CPPS}) target_link_libraries(libmve PRIVATE SDL2::SDL2) +target_include_directories(libmve PUBLIC + $ +) diff --git a/libmve/decoder16.c b/libmve/decoder16.c index 26ecb83d..20555b3c 100644 --- a/libmve/decoder16.c +++ b/libmve/decoder16.c @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2002-2024 D2X Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + /* 16 bit decoding routines */ #include @@ -9,708 +26,625 @@ static unsigned short *backBuf1, *backBuf2; static int lookup_initialized; -static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb); +static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, unsigned char **pData, + unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb); static void genLoopkupTable(void); -void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain) -{ - unsigned char *pOrig; - unsigned char *pOffData, *pEnd; - unsigned short offset; - unsigned short *FramePtr = (unsigned short *)pFrame; - int length; - int op; - int i, j; - int xb, yb; +void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain) { + unsigned char *pOrig; + unsigned char *pOffData, *pEnd; + unsigned short offset; + unsigned short *FramePtr = (unsigned short *)pFrame; + int length; + int op; + int i, j; + int xb, yb; - if (!lookup_initialized) { - genLoopkupTable(); - } + if (!lookup_initialized) { + genLoopkupTable(); + } - backBuf1 = (unsigned short *)g_vBackBuf1; - backBuf2 = (unsigned short *)g_vBackBuf2; + backBuf1 = (unsigned short *)g_vBackBuf1; + backBuf2 = (unsigned short *)g_vBackBuf2; - xb = g_width >> 3; - yb = g_height >> 3; + xb = g_width >> 3; + yb = g_height >> 3; - offset = pData[0]|(pData[1]<<8); + offset = pData[0] | (pData[1] << 8); - pOffData = pData + offset; - pEnd = pData + offset; + pOffData = pData + offset; + pEnd = pData + offset; - pData += 2; + pData += 2; - pOrig = pData; - length = offset - 2; /*dataRemain-2;*/ + pOrig = pData; + length = offset - 2; /*dataRemain-2;*/ - for (j=0; j= backBuf1 + g_width*g_height) - fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf); - */ + /* + if (FramePtr < backBuf1) + fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) + & 0xf); else if (FramePtr >= backBuf1 + g_width*g_height) fprintf(stderr, "danger! pointing out of bounds above + after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf); + */ - op = ((*pMap) >> 4) & 0xf; - dispatchDecoder16(&FramePtr, op, &pData, &pOffData, &dataRemain, &i, &j); + op = ((*pMap) >> 4) & 0xf; + dispatchDecoder16(&FramePtr, op, &pData, &pOffData, &dataRemain, &i, &j); - /* - if (FramePtr < backBuf1) - fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4); - else if (FramePtr >= backBuf1 + g_width*g_height) - fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4); - */ + /* + if (FramePtr < backBuf1) + fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) + >> 4); else if (FramePtr >= backBuf1 + g_width*g_height) fprintf(stderr, "danger! pointing out of bounds above + after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4); + */ - ++pMap; - --mapRemain; - } - - FramePtr += 7*g_width; + ++pMap; + --mapRemain; } - if ( (length - (pData - pOrig)) != 0 ) - fprintf(stderr, "DEBUG: junk left over: %d,%d,%d\n", (int)(pData-pOrig), length, (int)(length-(pData-pOrig))); + FramePtr += 7 * g_width; + } + + if ((length - (pData - pOrig)) != 0) + fprintf(stderr, "DEBUG: junk left over: %d,%d,%d\n", (int)(pData - pOrig), length, (int)(length - (pData - pOrig))); } -static unsigned short GETPIXEL(unsigned char **buf, int off) -{ - unsigned short val = (*buf)[0+off] | ((*buf)[1+off] << 8); - return val; +static unsigned short GETPIXEL(unsigned char **buf, int off) { + unsigned short val = (*buf)[0 + off] | ((*buf)[1 + off] << 8); + return val; } -static unsigned short GETPIXELI(unsigned char **buf, int off) -{ - unsigned short val = (*buf)[0+off] | ((*buf)[1+off] << 8); - (*buf) += 2; - return val; +static unsigned short GETPIXELI(unsigned char **buf, int off) { + unsigned short val = (*buf)[0 + off] | ((*buf)[1 + off] << 8); + (*buf) += 2; + return val; } -static void relClose(int i, int *x, int *y) -{ - int ma, mi; +static void relClose(int i, int *x, int *y) { + int ma, mi; - ma = i >> 4; - mi = i & 0xf; + ma = i >> 4; + mi = i & 0xf; - *x = mi - 8; - *y = ma - 8; + *x = mi - 8; + *y = ma - 8; } -static void relFar(int i, int sign, int *x, int *y) -{ - if (i < 56) - { - *x = sign * (8 + (i % 7)); - *y = sign * (i / 7); - } - else - { - *x = sign * (-14 + (i - 56) % 29); - *y = sign * (8 + (i - 56) / 29); - } +static void relFar(int i, int sign, int *x, int *y) { + if (i < 56) { + *x = sign * (8 + (i % 7)); + *y = sign * (i / 7); + } else { + *x = sign * (-14 + (i - 56) % 29); + *y = sign * (8 + (i - 56) / 29); + } } static int close_table[512]; static int far_p_table[512]; static int far_n_table[512]; -static void genLoopkupTable() -{ - int i; - int x, y; +static void genLoopkupTable() { + int i; + int x, y; - for (i = 0; i < 256; i++) { - relClose(i, &x, &y); + for (i = 0; i < 256; i++) { + relClose(i, &x, &y); - close_table[i*2+0] = x; - close_table[i*2+1] = y; + close_table[i * 2 + 0] = x; + close_table[i * 2 + 1] = y; - relFar(i, 1, &x, &y); + relFar(i, 1, &x, &y); - far_p_table[i*2+0] = x; - far_p_table[i*2+1] = y; + far_p_table[i * 2 + 0] = x; + far_p_table[i * 2 + 1] = y; - relFar(i, -1, &x, &y); + relFar(i, -1, &x, &y); - far_n_table[i*2+0] = x; - far_n_table[i*2+1] = y; - } + far_n_table[i * 2 + 0] = x; + far_n_table[i * 2 + 1] = y; + } - lookup_initialized = 1; + lookup_initialized = 1; } -static void copyFrame(unsigned short *pDest, unsigned short *pSrc) -{ - int i; +static void copyFrame(unsigned short *pDest, unsigned short *pSrc) { + int i; - for (i=0; i<8; i++) - { - memcpy(pDest, pSrc, 16); - pDest += g_width; - pSrc += g_width; + for (i = 0; i < 8; i++) { + memcpy(pDest, pSrc, 16); + pDest += g_width; + pSrc += g_width; + } +} + +static void patternRow4Pixels(unsigned short *pFrame, unsigned char pat0, unsigned char pat1, unsigned short *p) { + unsigned short mask = 0x0003; + unsigned short shift = 0; + unsigned short pattern = (pat1 << 8) | pat0; + + while (mask != 0) { + *pFrame++ = p[(mask & pattern) >> shift]; + mask <<= 2; + shift += 2; + } +} + +static void patternRow4Pixels2(unsigned short *pFrame, unsigned char pat0, unsigned short *p) { + unsigned char mask = 0x03; + unsigned char shift = 0; + unsigned short pel; + /* ORIGINAL VERSION IS BUGGY + int skip=1; + + while (mask != 0) + { + pel = p[(mask & pat0) >> shift]; + pFrame[0] = pel; + pFrame[2] = pel; + pFrame[g_width + 0] = pel; + pFrame[g_width + 2] = pel; + pFrame += skip; + skip = 4 - skip; + mask <<= 2; + shift += 2; + } + */ + while (mask != 0) { + pel = p[(mask & pat0) >> shift]; + pFrame[0] = pel; + pFrame[1] = pel; + pFrame[g_width + 0] = pel; + pFrame[g_width + 1] = pel; + pFrame += 2; + mask <<= 2; + shift += 2; + } +} + +static void patternRow4Pixels2x1(unsigned short *pFrame, unsigned char pat, unsigned short *p) { + unsigned char mask = 0x03; + unsigned char shift = 0; + unsigned short pel; + + while (mask != 0) { + pel = p[(mask & pat) >> shift]; + pFrame[0] = pel; + pFrame[1] = pel; + pFrame += 2; + mask <<= 2; + shift += 2; + } +} + +static void patternQuadrant4Pixels(unsigned short *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, + unsigned char pat3, unsigned short *p) { + unsigned long mask = 0x00000003UL; + int shift = 0; + int i; + unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0; + + for (i = 0; i < 16; i++) { + pFrame[i & 3] = p[(pat & mask) >> shift]; + + if ((i & 3) == 3) + pFrame += g_width; + + mask <<= 2; + shift += 2; + } +} + +static void patternRow2Pixels(unsigned short *pFrame, unsigned char pat, unsigned short *p) { + unsigned char mask = 0x01; + + while (mask != 0) { + *pFrame++ = p[(mask & pat) ? 1 : 0]; + mask <<= 1; + } +} + +static void patternRow2Pixels2(unsigned short *pFrame, unsigned char pat, unsigned short *p) { + unsigned short pel; + unsigned char mask = 0x1; + + /* ORIGINAL VERSION IS BUGGY + int skip=1; + while (mask != 0x10) + { + pel = p[(mask & pat) ? 1 : 0]; + pFrame[0] = pel; + pFrame[2] = pel; + pFrame[g_width + 0] = pel; + pFrame[g_width + 2] = pel; + pFrame += skip; + skip = 4 - skip; + mask <<= 1; + } + */ + while (mask != 0x10) { + pel = p[(mask & pat) ? 1 : 0]; + + pFrame[0] = pel; + pFrame[1] = pel; + pFrame[g_width + 0] = pel; + pFrame[g_width + 1] = pel; + pFrame += 2; + + mask <<= 1; + } +} + +static void patternQuadrant2Pixels(unsigned short *pFrame, unsigned char pat0, unsigned char pat1, unsigned short *p) { + unsigned short mask = 0x0001; + int i; + unsigned short pat = (pat1 << 8) | pat0; + + for (i = 0; i < 16; i++) { + pFrame[i & 3] = p[(pat & mask) ? 1 : 0]; + + if ((i & 3) == 3) + pFrame += g_width; + + mask <<= 1; + } +} + +static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, unsigned char **pData, + unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb) { + unsigned short p[4]; + unsigned char pat[16]; + int i, j, k; + int x, y; + unsigned short *pDstBak; + + pDstBak = *pFrame; + + switch (codeType) { + case 0x0: + copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1)); + case 0x1: + break; + case 0x2: /* + relFar(*(*pOffData)++, 1, &x, &y); + */ + + k = *(*pOffData)++; + x = far_p_table[k * 2 + 0]; + y = far_p_table[k * 2 + 1]; + + copyFrame(*pFrame, *pFrame + x + y * g_width); + --*pDataRemain; + break; + case 0x3: /* + relFar(*(*pOffData)++, -1, &x, &y); + */ + + k = *(*pOffData)++; + x = far_n_table[k * 2 + 0]; + y = far_n_table[k * 2 + 1]; + + copyFrame(*pFrame, *pFrame + x + y * g_width); + --*pDataRemain; + break; + case 0x4: /* + relClose(*(*pOffData)++, &x, &y); + */ + + k = *(*pOffData)++; + x = close_table[k * 2 + 0]; + y = close_table[k * 2 + 1]; + + copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y * g_width); + --*pDataRemain; + break; + case 0x5: + x = (char)*(*pData)++; + y = (char)*(*pData)++; + copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y * g_width); + *pDataRemain -= 2; + break; + case 0x6: + fprintf(stderr, "STUB: encoding 6 not tested\n"); + for (i = 0; i < 2; i++) { + *pFrame += 16; + if (++*curXb == (g_width >> 3)) { + *pFrame += 7 * g_width; + *curXb = 0; + if (++*curYb == (g_height >> 3)) + return; + } } -} + break; -static void patternRow4Pixels(unsigned short *pFrame, - unsigned char pat0, unsigned char pat1, - unsigned short *p) -{ - unsigned short mask=0x0003; - unsigned short shift=0; - unsigned short pattern = (pat1 << 8) | pat0; + case 0x7: + p[0] = GETPIXELI(pData, 0); + p[1] = GETPIXELI(pData, 0); - while (mask != 0) - { - *pFrame++ = p[(mask & pattern) >> shift]; - mask <<= 2; - shift += 2; + if (!((p[0] /*|p[1]*/) & 0x8000)) { + for (i = 0; i < 8; i++) { + patternRow2Pixels(*pFrame, *(*pData), p); + (*pData)++; + + *pFrame += g_width; + } + } else { + for (i = 0; i < 2; i++) { + patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p); + *pFrame += 2 * g_width; + patternRow2Pixels2(*pFrame, *(*pData) >> 4, p); + (*pData)++; + + *pFrame += 2 * g_width; + } } -} + break; -static void patternRow4Pixels2(unsigned short *pFrame, - unsigned char pat0, - unsigned short *p) -{ - unsigned char mask=0x03; - unsigned char shift=0; - unsigned short pel; - /* ORIGINAL VERSION IS BUGGY - int skip=1; + case 0x8: + p[0] = GETPIXEL(pData, 0); - while (mask != 0) - { - pel = p[(mask & pat0) >> shift]; - pFrame[0] = pel; - pFrame[2] = pel; - pFrame[g_width + 0] = pel; - pFrame[g_width + 2] = pel; - pFrame += skip; - skip = 4 - skip; - mask <<= 2; - shift += 2; - } - */ - while (mask != 0) - { - pel = p[(mask & pat0) >> shift]; - pFrame[0] = pel; - pFrame[1] = pel; - pFrame[g_width + 0] = pel; - pFrame[g_width + 1] = pel; - pFrame += 2; - mask <<= 2; - shift += 2; + if (!(p[0] & 0x8000)) { + for (i = 0; i < 4; i++) { + p[0] = GETPIXELI(pData, 0); + p[1] = GETPIXELI(pData, 0); + + pat[0] = (*pData)[0]; + pat[1] = (*pData)[1]; + (*pData) += 2; + + patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); + + if (i & 1) + *pFrame -= (4 * g_width - 4); + else + *pFrame += 4 * g_width; + } + + } else { + p[2] = GETPIXEL(pData, 8); + + if (!(p[2] & 0x8000)) { + for (i = 0; i < 4; i++) { + if ((i & 1) == 0) { + p[0] = GETPIXELI(pData, 0); + p[1] = GETPIXELI(pData, 0); + } + pat[0] = *(*pData)++; + pat[1] = *(*pData)++; + patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); + + if (i & 1) + *pFrame -= (4 * g_width - 4); + else + *pFrame += 4 * g_width; + } + } else { + for (i = 0; i < 8; i++) { + if ((i & 3) == 0) { + p[0] = GETPIXELI(pData, 0); + p[1] = GETPIXELI(pData, 0); + } + patternRow2Pixels(*pFrame, *(*pData), p); + (*pData)++; + + *pFrame += g_width; + } + } } -} + break; -static void patternRow4Pixels2x1(unsigned short *pFrame, unsigned char pat, - unsigned short *p) -{ - unsigned char mask=0x03; - unsigned char shift=0; - unsigned short pel; + case 0x9: + p[0] = GETPIXELI(pData, 0); + p[1] = GETPIXELI(pData, 0); + p[2] = GETPIXELI(pData, 0); + p[3] = GETPIXELI(pData, 0); - while (mask != 0) - { - pel = p[(mask & pat) >> shift]; - pFrame[0] = pel; - pFrame[1] = pel; - pFrame += 2; - mask <<= 2; - shift += 2; + *pDataRemain -= 8; + + if (!(p[0] & 0x8000)) { + if (!(p[2] & 0x8000)) { + + for (i = 0; i < 8; i++) { + pat[0] = (*pData)[0]; + pat[1] = (*pData)[1]; + (*pData) += 2; + patternRow4Pixels(*pFrame, pat[0], pat[1], p); + *pFrame += g_width; + } + *pDataRemain -= 16; + + } else { + patternRow4Pixels2(*pFrame, (*pData)[0], p); + *pFrame += 2 * g_width; + patternRow4Pixels2(*pFrame, (*pData)[1], p); + *pFrame += 2 * g_width; + patternRow4Pixels2(*pFrame, (*pData)[2], p); + *pFrame += 2 * g_width; + patternRow4Pixels2(*pFrame, (*pData)[3], p); + + (*pData) += 4; + *pDataRemain -= 4; + } + } else { + if (!(p[2] & 0x8000)) { + for (i = 0; i < 8; i++) { + pat[0] = (*pData)[0]; + (*pData) += 1; + patternRow4Pixels2x1(*pFrame, pat[0], p); + *pFrame += g_width; + } + *pDataRemain -= 8; + } else { + for (i = 0; i < 4; i++) { + pat[0] = (*pData)[0]; + pat[1] = (*pData)[1]; + + (*pData) += 2; + + patternRow4Pixels(*pFrame, pat[0], pat[1], p); + *pFrame += g_width; + patternRow4Pixels(*pFrame, pat[0], pat[1], p); + *pFrame += g_width; + } + *pDataRemain -= 8; + } } -} + break; -static void patternQuadrant4Pixels(unsigned short *pFrame, - unsigned char pat0, unsigned char pat1, unsigned char pat2, - unsigned char pat3, unsigned short *p) -{ - unsigned long mask = 0x00000003UL; - int shift=0; - int i; - unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0; + case 0xa: + p[0] = GETPIXEL(pData, 0); - for (i=0; i<16; i++) - { - pFrame[i&3] = p[(pat & mask) >> shift]; + if (!(p[0] & 0x8000)) { + for (i = 0; i < 4; i++) { + p[0] = GETPIXELI(pData, 0); + p[1] = GETPIXELI(pData, 0); + p[2] = GETPIXELI(pData, 0); + p[3] = GETPIXELI(pData, 0); + pat[0] = (*pData)[0]; + pat[1] = (*pData)[1]; + pat[2] = (*pData)[2]; + pat[3] = (*pData)[3]; - if ((i&3) == 3) - pFrame += g_width; + (*pData) += 4; - mask <<= 2; - shift += 2; + patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); + + if (i & 1) + *pFrame -= (4 * g_width - 4); + else + *pFrame += 4 * g_width; + } + } else { + p[0] = GETPIXEL(pData, 16); + + if (!(p[0] & 0x8000)) { + for (i = 0; i < 4; i++) { + if ((i & 1) == 0) { + p[0] = GETPIXELI(pData, 0); + p[1] = GETPIXELI(pData, 0); + p[2] = GETPIXELI(pData, 0); + p[3] = GETPIXELI(pData, 0); + } + + pat[0] = (*pData)[0]; + pat[1] = (*pData)[1]; + pat[2] = (*pData)[2]; + pat[3] = (*pData)[3]; + + (*pData) += 4; + + patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); + + if (i & 1) + *pFrame -= (4 * g_width - 4); + else + *pFrame += 4 * g_width; + } + } else { + for (i = 0; i < 8; i++) { + if ((i & 3) == 0) { + p[0] = GETPIXELI(pData, 0); + p[1] = GETPIXELI(pData, 0); + p[2] = GETPIXELI(pData, 0); + p[3] = GETPIXELI(pData, 0); + } + + pat[0] = (*pData)[0]; + pat[1] = (*pData)[1]; + patternRow4Pixels(*pFrame, pat[0], pat[1], p); + *pFrame += g_width; + + (*pData) += 2; + } + } } -} + break; - -static void patternRow2Pixels(unsigned short *pFrame, unsigned char pat, - unsigned short *p) -{ - unsigned char mask=0x01; - - while (mask != 0) - { - *pFrame++ = p[(mask & pat) ? 1 : 0]; - mask <<= 1; + case 0xb: + for (i = 0; i < 8; i++) { + memcpy(*pFrame, *pData, 16); + *pFrame += g_width; + *pData += 16; + *pDataRemain -= 16; } -} + break; -static void patternRow2Pixels2(unsigned short *pFrame, unsigned char pat, - unsigned short *p) -{ - unsigned short pel; - unsigned char mask=0x1; + case 0xc: + for (i = 0; i < 4; i++) { + p[0] = GETPIXEL(pData, 0); + p[1] = GETPIXEL(pData, 2); + p[2] = GETPIXEL(pData, 4); + p[3] = GETPIXEL(pData, 6); - /* ORIGINAL VERSION IS BUGGY - int skip=1; - while (mask != 0x10) - { - pel = p[(mask & pat) ? 1 : 0]; - pFrame[0] = pel; - pFrame[2] = pel; - pFrame[g_width + 0] = pel; - pFrame[g_width + 2] = pel; - pFrame += skip; - skip = 4 - skip; - mask <<= 1; - } - */ - while (mask != 0x10) { - pel = p[(mask & pat) ? 1 : 0]; - - pFrame[0] = pel; - pFrame[1] = pel; - pFrame[g_width + 0] = pel; - pFrame[g_width + 1] = pel; - pFrame += 2; - - mask <<= 1; - } -} - -static void patternQuadrant2Pixels(unsigned short *pFrame, unsigned char pat0, - unsigned char pat1, unsigned short *p) -{ - unsigned short mask = 0x0001; - int i; - unsigned short pat = (pat1 << 8) | pat0; - - for (i=0; i<16; i++) - { - pFrame[i&3] = p[(pat & mask) ? 1 : 0]; - - if ((i&3) == 3) - pFrame += g_width; - - mask <<= 1; + for (j = 0; j < 2; j++) { + for (k = 0; k < 4; k++) { + (*pFrame)[j + 2 * k] = p[k]; + (*pFrame)[g_width + j + 2 * k] = p[k]; + } + *pFrame += g_width; + } + *pData += 8; + *pDataRemain -= 8; } -} + break; -static void dispatchDecoder16(unsigned short **pFrame, unsigned char codeType, unsigned char **pData, unsigned char **pOffData, int *pDataRemain, int *curXb, int *curYb) -{ - unsigned short p[4]; - unsigned char pat[16]; - int i, j, k; - int x, y; - unsigned short *pDstBak; + case 0xd: + for (i = 0; i < 2; i++) { + p[0] = GETPIXEL(pData, 0); + p[1] = GETPIXEL(pData, 2); - pDstBak = *pFrame; + for (j = 0; j < 4; j++) { + for (k = 0; k < 4; k++) { + (*pFrame)[k * g_width + j] = p[0]; + (*pFrame)[k * g_width + j + 4] = p[1]; + } + } - switch(codeType) - { - case 0x0: - copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1)); - case 0x1: - break; - case 0x2: /* - relFar(*(*pOffData)++, 1, &x, &y); - */ + *pFrame += 4 * g_width; - k = *(*pOffData)++; - x = far_p_table[k*2+0]; - y = far_p_table[k*2+1]; + *pData += 4; + *pDataRemain -= 4; + } + break; - copyFrame(*pFrame, *pFrame + x + y*g_width); - --*pDataRemain; - break; - case 0x3: /* - relFar(*(*pOffData)++, -1, &x, &y); - */ + case 0xe: + p[0] = GETPIXEL(pData, 0); - k = *(*pOffData)++; - x = far_n_table[k*2+0]; - y = far_n_table[k*2+1]; + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + (*pFrame)[j] = p[0]; + } - copyFrame(*pFrame, *pFrame + x + y*g_width); - --*pDataRemain; - break; - case 0x4: /* - relClose(*(*pOffData)++, &x, &y); - */ - - k = *(*pOffData)++; - x = close_table[k*2+0]; - y = close_table[k*2+1]; - - copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width); - --*pDataRemain; - break; - case 0x5: - x = (char)*(*pData)++; - y = (char)*(*pData)++; - copyFrame(*pFrame, *pFrame + (backBuf2 - backBuf1) + x + y*g_width); - *pDataRemain -= 2; - break; - case 0x6: - fprintf(stderr, "STUB: encoding 6 not tested\n"); - for (i=0; i<2; i++) - { - *pFrame += 16; - if (++*curXb == (g_width >> 3)) - { - *pFrame += 7*g_width; - *curXb = 0; - if (++*curYb == (g_height >> 3)) - return; - } - } - break; - - case 0x7: - p[0] = GETPIXELI(pData, 0); - p[1] = GETPIXELI(pData, 0); - - if (!((p[0]/*|p[1]*/)&0x8000)) - { - for (i=0; i<8; i++) - { - patternRow2Pixels(*pFrame, *(*pData), p); - (*pData)++; - - *pFrame += g_width; - } - } - else - { - for (i=0; i<2; i++) - { - patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p); - *pFrame += 2*g_width; - patternRow2Pixels2(*pFrame, *(*pData) >> 4, p); - (*pData)++; - - *pFrame += 2*g_width; - } - } - break; - - case 0x8: - p[0] = GETPIXEL(pData, 0); - - if (!(p[0] & 0x8000)) - { - for (i=0; i<4; i++) - { - p[0] = GETPIXELI(pData, 0); - p[1] = GETPIXELI(pData, 0); - - pat[0] = (*pData)[0]; - pat[1] = (*pData)[1]; - (*pData) += 2; - - patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); - - if (i & 1) - *pFrame -= (4*g_width - 4); - else - *pFrame += 4*g_width; - } - - - } else { - p[2] = GETPIXEL(pData, 8); - - if (!(p[2]&0x8000)) { - for (i=0; i<4; i++) - { - if ((i & 1) == 0) - { - p[0] = GETPIXELI(pData, 0); - p[1] = GETPIXELI(pData, 0); - } - pat[0] = *(*pData)++; - pat[1] = *(*pData)++; - patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); - - if (i & 1) - *pFrame -= (4*g_width - 4); - else - *pFrame += 4*g_width; - } - } else { - for (i=0; i<8; i++) - { - if ((i & 3) == 0) - { - p[0] = GETPIXELI(pData, 0); - p[1] = GETPIXELI(pData, 0); - } - patternRow2Pixels(*pFrame, *(*pData), p); - (*pData)++; - - *pFrame += g_width; - } - } - } - break; - - case 0x9: - p[0] = GETPIXELI(pData, 0); - p[1] = GETPIXELI(pData, 0); - p[2] = GETPIXELI(pData, 0); - p[3] = GETPIXELI(pData, 0); - - *pDataRemain -= 8; - - if (!(p[0] & 0x8000)) - { - if (!(p[2] & 0x8000)) - { - - for (i=0; i<8; i++) - { - pat[0] = (*pData)[0]; - pat[1] = (*pData)[1]; - (*pData) += 2; - patternRow4Pixels(*pFrame, pat[0], pat[1], p); - *pFrame += g_width; - } - *pDataRemain -= 16; - - } - else - { - patternRow4Pixels2(*pFrame, (*pData)[0], p); - *pFrame += 2*g_width; - patternRow4Pixels2(*pFrame, (*pData)[1], p); - *pFrame += 2*g_width; - patternRow4Pixels2(*pFrame, (*pData)[2], p); - *pFrame += 2*g_width; - patternRow4Pixels2(*pFrame, (*pData)[3], p); - - (*pData) += 4; - *pDataRemain -= 4; - - } - } - else - { - if (!(p[2] & 0x8000)) - { - for (i=0; i<8; i++) - { - pat[0] = (*pData)[0]; - (*pData) += 1; - patternRow4Pixels2x1(*pFrame, pat[0], p); - *pFrame += g_width; - } - *pDataRemain -= 8; - } - else - { - for (i=0; i<4; i++) - { - pat[0] = (*pData)[0]; - pat[1] = (*pData)[1]; - - (*pData) += 2; - - patternRow4Pixels(*pFrame, pat[0], pat[1], p); - *pFrame += g_width; - patternRow4Pixels(*pFrame, pat[0], pat[1], p); - *pFrame += g_width; - } - *pDataRemain -= 8; - } - } - break; - - case 0xa: - p[0] = GETPIXEL(pData, 0); - - if (!(p[0] & 0x8000)) - { - for (i=0; i<4; i++) - { - p[0] = GETPIXELI(pData, 0); - p[1] = GETPIXELI(pData, 0); - p[2] = GETPIXELI(pData, 0); - p[3] = GETPIXELI(pData, 0); - pat[0] = (*pData)[0]; - pat[1] = (*pData)[1]; - pat[2] = (*pData)[2]; - pat[3] = (*pData)[3]; - - (*pData) += 4; - - patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); - - if (i & 1) - *pFrame -= (4*g_width - 4); - else - *pFrame += 4*g_width; - } - } - else - { - p[0] = GETPIXEL(pData, 16); - - if (!(p[0] & 0x8000)) - { - for (i=0; i<4; i++) - { - if ((i&1) == 0) - { - p[0] = GETPIXELI(pData, 0); - p[1] = GETPIXELI(pData, 0); - p[2] = GETPIXELI(pData, 0); - p[3] = GETPIXELI(pData, 0); - } - - pat[0] = (*pData)[0]; - pat[1] = (*pData)[1]; - pat[2] = (*pData)[2]; - pat[3] = (*pData)[3]; - - (*pData) += 4; - - patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); - - if (i & 1) - *pFrame -= (4*g_width - 4); - else - *pFrame += 4*g_width; - } - } - else - { - for (i=0; i<8; i++) - { - if ((i&3) == 0) - { - p[0] = GETPIXELI(pData, 0); - p[1] = GETPIXELI(pData, 0); - p[2] = GETPIXELI(pData, 0); - p[3] = GETPIXELI(pData, 0); - } - - pat[0] = (*pData)[0]; - pat[1] = (*pData)[1]; - patternRow4Pixels(*pFrame, pat[0], pat[1], p); - *pFrame += g_width; - - (*pData) += 2; - } - } - } - break; - - case 0xb: - for (i=0; i<8; i++) - { - memcpy(*pFrame, *pData, 16); - *pFrame += g_width; - *pData += 16; - *pDataRemain -= 16; - } - break; - - case 0xc: - for (i=0; i<4; i++) - { - p[0] = GETPIXEL(pData, 0); - p[1] = GETPIXEL(pData, 2); - p[2] = GETPIXEL(pData, 4); - p[3] = GETPIXEL(pData, 6); - - for (j=0; j<2; j++) - { - for (k=0; k<4; k++) - { - (*pFrame)[j+2*k] = p[k]; - (*pFrame)[g_width+j+2*k] = p[k]; - } - *pFrame += g_width; - } - *pData += 8; - *pDataRemain -= 8; - } - break; - - case 0xd: - for (i=0; i<2; i++) - { - p[0] = GETPIXEL(pData, 0); - p[1] = GETPIXEL(pData, 2); - - for (j=0; j<4; j++) - { - for (k=0; k<4; k++) - { - (*pFrame)[k*g_width+j] = p[0]; - (*pFrame)[k*g_width+j+4] = p[1]; - } - } - - *pFrame += 4*g_width; - - *pData += 4; - *pDataRemain -= 4; - } - break; - - case 0xe: - p[0] = GETPIXEL(pData, 0); - - for (i = 0; i < 8; i++) { - for (j = 0; j < 8; j++) { - (*pFrame)[j] = p[0]; - } - - *pFrame += g_width; - } - - *pData += 2; - *pDataRemain -= 2; - - break; - - case 0xf: - p[0] = GETPIXEL(pData, 0); - p[1] = GETPIXEL(pData, 1); - - for (i=0; i<8; i++) - { - for (j=0; j<8; j++) - { - (*pFrame)[j] = p[(i+j)&1]; - } - *pFrame += g_width; - } - - *pData += 4; - *pDataRemain -= 4; - break; - - default: - break; + *pFrame += g_width; } - *pFrame = pDstBak+8; + *pData += 2; + *pDataRemain -= 2; + + break; + + case 0xf: + p[0] = GETPIXEL(pData, 0); + p[1] = GETPIXEL(pData, 1); + + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + (*pFrame)[j] = p[(i + j) & 1]; + } + *pFrame += g_width; + } + + *pData += 4; + *pDataRemain -= 4; + break; + + default: + break; + } + + *pFrame = pDstBak + 8; } diff --git a/libmve/decoder8.c b/libmve/decoder8.c index a676e00b..722faf4e 100644 --- a/libmve/decoder8.c +++ b/libmve/decoder8.c @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2002-2024 D2X Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + /* 8 bit decoding routines */ #include @@ -5,867 +22,793 @@ #include "decoders.h" -static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb); +static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, + int *curXb, int *curYb); -void decodeFrame8(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain) -{ - int i, j; - int xb, yb; +void decodeFrame8(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain) { + int i, j; + int xb, yb; - xb = g_width >> 3; - yb = g_height >> 3; - for (j=0; j= ((unsigned char *)g_vBackBuf1) + g_width*g_height) - fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, (*pMap) & 0xf); - dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j); - if (pFrame < (unsigned char *)g_vBackBuf1) - fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4); - else if (pFrame >= ((unsigned char *)g_vBackBuf1) + g_width*g_height) - fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, (*pMap) >> 4); + xb = g_width >> 3; + yb = g_height >> 3; + for (j = 0; j < yb; j++) { + for (i = 0; i < xb / 2; i++) { + dispatchDecoder(&pFrame, (*pMap) & 0xf, &pData, &dataRemain, &i, &j); + if (pFrame < (unsigned char *)g_vBackBuf1) + fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (1) [%x]\n", i, j, + (*pMap) & 0xf); + else if (pFrame >= ((unsigned char *)g_vBackBuf1) + g_width * g_height) + fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (1) [%x]\n", i, j, + (*pMap) & 0xf); + dispatchDecoder(&pFrame, (*pMap) >> 4, &pData, &dataRemain, &i, &j); + if (pFrame < (unsigned char *)g_vBackBuf1) + fprintf(stderr, "danger! pointing out of bounds below after dispatch decoder: %d, %d (2) [%x]\n", i, j, + (*pMap) >> 4); + else if (pFrame >= ((unsigned char *)g_vBackBuf1) + g_width * g_height) + fprintf(stderr, "danger! pointing out of bounds above after dispatch decoder: %d, %d (2) [%x]\n", i, j, + (*pMap) >> 4); - ++pMap; - --mapRemain; - } + ++pMap; + --mapRemain; + } - pFrame += 7*g_width; - } + pFrame += 7 * g_width; + } } -static void relClose(int i, int *x, int *y) -{ - int ma, mi; +static void relClose(int i, int *x, int *y) { + int ma, mi; - ma = i >> 4; - mi = i & 0xf; + ma = i >> 4; + mi = i & 0xf; - *x = mi - 8; - *y = ma - 8; + *x = mi - 8; + *y = ma - 8; } -static void relFar(int i, int sign, int *x, int *y) -{ - if (i < 56) - { - *x = sign * (8 + (i % 7)); - *y = sign * (i / 7); - } - else - { - *x = sign * (-14 + (i - 56) % 29); - *y = sign * (8 + (i - 56) / 29); - } +static void relFar(int i, int sign, int *x, int *y) { + if (i < 56) { + *x = sign * (8 + (i % 7)); + *y = sign * (i / 7); + } else { + *x = sign * (-14 + (i - 56) % 29); + *y = sign * (8 + (i - 56) / 29); + } } /* copies an 8x8 block from pSrc to pDest. pDest and pSrc are both g_width bytes wide */ -static void copyFrame(unsigned char *pDest, unsigned char *pSrc) -{ - int i; +static void copyFrame(unsigned char *pDest, unsigned char *pSrc) { + int i; - for (i=0; i<8; i++) - { - memcpy(pDest, pSrc, 8); - pDest += g_width; - pSrc += g_width; - } + for (i = 0; i < 8; i++) { + memcpy(pDest, pSrc, 8); + pDest += g_width; + pSrc += g_width; + } } // Fill in the next eight bytes with p[0], p[1], p[2], or p[3], // depending on the corresponding two-bit value in pat0 and pat1 -static void patternRow4Pixels(unsigned char *pFrame, - unsigned char pat0, unsigned char pat1, - unsigned char *p) -{ - unsigned short mask=0x0003; - unsigned short shift=0; - unsigned short pattern = (pat1 << 8) | pat0; +static void patternRow4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p) { + unsigned short mask = 0x0003; + unsigned short shift = 0; + unsigned short pattern = (pat1 << 8) | pat0; - while (mask != 0) - { - *pFrame++ = p[(mask & pattern) >> shift]; - mask <<= 2; - shift += 2; - } + while (mask != 0) { + *pFrame++ = p[(mask & pattern) >> shift]; + mask <<= 2; + shift += 2; + } } // Fill in the next four 2x2 pixel blocks with p[0], p[1], p[2], or p[3], // depending on the corresponding two-bit value in pat0. -static void patternRow4Pixels2(unsigned char *pFrame, - unsigned char pat0, - unsigned char *p) -{ - unsigned char mask=0x03; - unsigned char shift=0; - unsigned char pel; +static void patternRow4Pixels2(unsigned char *pFrame, unsigned char pat0, unsigned char *p) { + unsigned char mask = 0x03; + unsigned char shift = 0; + unsigned char pel; - while (mask != 0) - { - pel = p[(mask & pat0) >> shift]; - pFrame[0] = pel; - pFrame[1] = pel; - pFrame[g_width + 0] = pel; - pFrame[g_width + 1] = pel; - pFrame += 2; - mask <<= 2; - shift += 2; - } + while (mask != 0) { + pel = p[(mask & pat0) >> shift]; + pFrame[0] = pel; + pFrame[1] = pel; + pFrame[g_width + 0] = pel; + pFrame[g_width + 1] = pel; + pFrame += 2; + mask <<= 2; + shift += 2; + } } // Fill in the next four 2x1 pixel blocks with p[0], p[1], p[2], or p[3], // depending on the corresponding two-bit value in pat. -static void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p) -{ - unsigned char mask=0x03; - unsigned char shift=0; - unsigned char pel; +static void patternRow4Pixels2x1(unsigned char *pFrame, unsigned char pat, unsigned char *p) { + unsigned char mask = 0x03; + unsigned char shift = 0; + unsigned char pel; - while (mask != 0) - { - pel = p[(mask & pat) >> shift]; - pFrame[0] = pel; - pFrame[1] = pel; - pFrame += 2; - mask <<= 2; - shift += 2; - } + while (mask != 0) { + pel = p[(mask & pat) >> shift]; + pFrame[0] = pel; + pFrame[1] = pel; + pFrame += 2; + mask <<= 2; + shift += 2; + } } // Fill in the next 4x4 pixel block with p[0], p[1], p[2], or p[3], // depending on the corresponding two-bit value in pat0, pat1, pat2, and pat3. -static void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, unsigned char pat3, unsigned char *p) -{ - unsigned long mask = 0x00000003UL; - int shift=0; - int i; - unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0; +static void patternQuadrant4Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char pat2, + unsigned char pat3, unsigned char *p) { + unsigned long mask = 0x00000003UL; + int shift = 0; + int i; + unsigned long pat = (pat3 << 24) | (pat2 << 16) | (pat1 << 8) | pat0; - for (i=0; i<16; i++) - { - pFrame[i&3] = p[(pat & mask) >> shift]; + for (i = 0; i < 16; i++) { + pFrame[i & 3] = p[(pat & mask) >> shift]; - if ((i&3) == 3) - pFrame += g_width; + if ((i & 3) == 3) + pFrame += g_width; - mask <<= 2; - shift += 2; - } + mask <<= 2; + shift += 2; + } } // fills the next 8 pixels with either p[0] or p[1], depending on pattern -static void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p) -{ - unsigned char mask=0x01; +static void patternRow2Pixels(unsigned char *pFrame, unsigned char pat, unsigned char *p) { + unsigned char mask = 0x01; - while (mask != 0) - { - *pFrame++ = p[(mask & pat) ? 1 : 0]; - mask <<= 1; - } + while (mask != 0) { + *pFrame++ = p[(mask & pat) ? 1 : 0]; + mask <<= 1; + } } // fills the next four 2 x 2 pixel boxes with either p[0] or p[1], depending on pattern -static void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p) -{ - unsigned char pel; - unsigned char mask=0x1; +static void patternRow2Pixels2(unsigned char *pFrame, unsigned char pat, unsigned char *p) { + unsigned char pel; + unsigned char mask = 0x1; - while (mask != 0x10) - { - pel = p[(mask & pat) ? 1 : 0]; + while (mask != 0x10) { + pel = p[(mask & pat) ? 1 : 0]; - pFrame[0] = pel; // upper-left - pFrame[1] = pel; // upper-right - pFrame[g_width + 0] = pel; // lower-left - pFrame[g_width + 1] = pel; // lower-right - pFrame += 2; + pFrame[0] = pel; // upper-left + pFrame[1] = pel; // upper-right + pFrame[g_width + 0] = pel; // lower-left + pFrame[g_width + 1] = pel; // lower-right + pFrame += 2; - mask <<= 1; - } + mask <<= 1; + } } // fills pixels in the next 4 x 4 pixel boxes with either p[0] or p[1], depending on pat0 and pat1. -static void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p) -{ - unsigned char pel; - unsigned short mask = 0x0001; - int i, j; - unsigned short pat = (pat1 << 8) | pat0; +static void patternQuadrant2Pixels(unsigned char *pFrame, unsigned char pat0, unsigned char pat1, unsigned char *p) { + unsigned char pel; + unsigned short mask = 0x0001; + int i, j; + unsigned short pat = (pat1 << 8) | pat0; - for (i=0; i<4; i++) - { - for (j=0; j<4; j++) - { - pel = p[(pat & mask) ? 1 : 0]; + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + pel = p[(pat & mask) ? 1 : 0]; - pFrame[j + i * g_width] = pel; + pFrame[j + i * g_width] = pel; - mask <<= 1; - } - } + mask <<= 1; + } + } } -static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, int *curXb, int *curYb) -{ - unsigned char p[4]; - unsigned char pat[16]; - int i, j, k; - int x, y; - - /* Data is processed in 8x8 pixel blocks. - There are 16 ways to encode each block. - */ - - switch(codeType) - { - case 0x0: - /* block is copied from block in current frame */ - copyFrame(*pFrame, *pFrame + ((unsigned char *)g_vBackBuf2 - (unsigned char *)g_vBackBuf1)); - case 0x1: - /* block is unchanged from two frames ago */ - *pFrame += 8; - break; - - case 0x2: - /* Block is copied from nearby (below and/or to the right) within the - new frame. The offset within the buffer from which to grab the - patch of 8 pixels is given by grabbing a byte B from the data - stream, which is broken into a positive x and y offset according - to the following mapping: - - if B < 56: - x = 8 + (B % 7) - y = B / 7 - else - x = -14 + ((B - 56) % 29) - y = 8 + ((B - 56) / 29) - */ - relFar(*(*pData)++, 1, &x, &y); - copyFrame(*pFrame, *pFrame + x + y*g_width); - *pFrame += 8; - --*pDataRemain; - break; - - case 0x3: - /* Block is copied from nearby (above and/or to the left) within the - new frame. - - if B < 56: - x = -(8 + (B % 7)) - y = -(B / 7) - else - x = -(-14 + ((B - 56) % 29)) - y = -( 8 + ((B - 56) / 29)) - */ - relFar(*(*pData)++, -1, &x, &y); - copyFrame(*pFrame, *pFrame + x + y*g_width); - *pFrame += 8; - --*pDataRemain; - break; - - case 0x4: - /* Similar to 0x2 and 0x3, except this method copies from the - "current" frame, rather than the "new" frame, and instead of the - lopsided mapping they use, this one uses one which is symmetric - and centered around the top-left corner of the block. This uses - only 1 byte still, though, so the range is decreased, since we - have to encode all directions in a single byte. The byte we pull - from the data stream, I'll call B. Call the highest 4 bits of B - BH and the lowest 4 bytes BL. Then the offset from which to copy - the data is: - - x = -8 + BL - y = -8 + BH - */ - relClose(*(*pData)++, &x, &y); - copyFrame(*pFrame, *pFrame + ((unsigned char *)g_vBackBuf2 - (unsigned char *)g_vBackBuf1) + x + y*g_width); - *pFrame += 8; - --*pDataRemain; - break; - - case 0x5: - /* Similar to 0x4, but instead of one byte for the offset, this uses - two bytes to encode a larger range, the first being the x offset - as a signed 8-bit value, and the second being the y offset as a - signed 8-bit value. - */ - x = (signed char)*(*pData)++; - y = (signed char)*(*pData)++; - copyFrame(*pFrame, *pFrame + ((unsigned char *)g_vBackBuf2 - (unsigned char *)g_vBackBuf1) + x + y*g_width); - *pFrame += 8; - *pDataRemain -= 2; - break; - - case 0x6: - /* I can't figure out how any file containing a block of this type - could still be playable, since it appears that it would leave the - internal bookkeeping in an inconsistent state in the BG player - code. Ahh, well. Perhaps it was a bug in the BG player code that - just didn't happen to be exposed by any of the included movies. - Anyway, this skips the next two blocks, doing nothing to them. - Note that if you've reached the end of a row, this means going on - to the next row. - */ - for (i=0; i<2; i++) - { - *pFrame += 16; - if (++*curXb == (g_width >> 3)) - { - *pFrame += 7*g_width; - *curXb = 0; - if (++*curYb == (g_height >> 3)) - return; - } - } - break; - - case 0x7: - /* Ok, here's where it starts to get really...interesting. This is, - incidentally, the part where they started using self-modifying - code. So, most of the following encodings are "patterned" blocks, - where we are given a number of pixel values and then bitmapped - values to specify which pixel values belong to which squares. For - this encoding, we are given the following in the data stream: - - P0 P1 - - These are pixel values (i.e. 8-bit indices into the palette). If - P0 <= P1, we then get 8 more bytes from the data stream, one for - each row in the block: - - B0 B1 B2 B3 B4 B5 B6 B7 - - For each row, the leftmost pixel is represented by the low-order - bit, and the rightmost by the high-order bit. Use your imagination - in between. If a bit is set, the pixel value is P1 and if it is - unset, the pixel value is P0. - - So, for example, if we had: - - 11 22 fe 83 83 83 83 83 83 fe - - This would represent the following layout: - - 11 22 22 22 22 22 22 22 ; fe == 11111110 - 22 22 11 11 11 11 11 22 ; 83 == 10000011 - 22 22 11 11 11 11 11 22 ; 83 == 10000011 - 22 22 11 11 11 11 11 22 ; 83 == 10000011 - 22 22 11 11 11 11 11 22 ; 83 == 10000011 - 22 22 11 11 11 11 11 22 ; 83 == 10000011 - 22 22 11 11 11 11 11 22 ; 83 == 10000011 - 11 22 22 22 22 22 22 22 ; fe == 11111110 - - If, on the other hand, P0 > P1, we get two more bytes from the - data stream: - - B0 B1 - - Each of these bytes contains two 4-bit patterns. These patterns - work like the patterns above with 8 bytes, except each bit - represents a 2x2 pixel region. - - B0 contains the pattern for the top two rows and B1 contains - the pattern for the bottom two rows. Note that the low-order - nibble of each byte contains the pattern for the upper of the - two rows that that byte controls. - - So if we had: - - 22 11 7e 83 - - The output would be: - - 11 11 22 22 22 22 22 22 ; e == 1 1 1 0 - 11 11 22 22 22 22 22 22 ; - 22 22 22 22 22 22 11 11 ; 7 == 0 1 1 1 - 22 22 22 22 22 22 11 11 ; - 11 11 11 11 11 11 22 22 ; 3 == 1 0 0 0 - 11 11 11 11 11 11 22 22 ; - 22 22 22 22 11 11 11 11 ; 8 == 0 0 1 1 - 22 22 22 22 11 11 11 11 ; - */ - p[0] = *(*pData)++; - p[1] = *(*pData)++; - if (p[0] <= p[1]) - { - for (i=0; i<8; i++) - { - patternRow2Pixels(*pFrame, *(*pData)++, p); - *pFrame += g_width; - } - } - else - { - for (i=0; i<2; i++) - { - patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p); - *pFrame += 2*g_width; - patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p); - *pFrame += 2*g_width; - } - } - *pFrame -= (8*g_width - 8); - break; - - case 0x8: - /* Ok, this one is basically like encoding 0x7, only more - complicated. Again, we start out by getting two bytes on the data - stream: - - P0 P1 - - if P0 <= P1 then we get the following from the data stream: - - B0 B1 - P2 P3 B2 B3 - P4 P5 B4 B5 - P6 P7 B6 B7 - - P0 P1 and B0 B1 are used for the top-left corner, P2 P3 B2 B3 for - the bottom-left corner, P4 P5 B4 B5 for the top-right, P6 P7 B6 B7 - for the bottom-right. (So, each codes for a 4x4 pixel array.) - Since we have 16 bits in B0 B1, there is one bit for each pixel in - the array. The convention for the bit-mapping is, again, left to - right and top to bottom. - - So, basically, the top-left quarter of the block is an arbitrary - pattern with 2 pixels, the bottom-left a different arbitrary - pattern with 2 different pixels, and so on. - - For example if the next 16 bytes were: - - 00 22 f9 9f 44 55 aa 55 11 33 cc 33 66 77 01 ef - - We'd draw: - - 22 22 22 22 | 11 11 33 33 ; f = 1111, c = 1100 - 22 00 00 22 | 11 11 33 33 ; 9 = 1001, c = 1100 - 22 00 00 22 | 33 33 11 11 ; 9 = 1001, 3 = 0011 - 22 22 22 22 | 33 33 11 11 ; f = 1111, 3 = 0011 - ------------+------------ - 44 55 44 55 | 66 66 66 66 ; a = 1010, 0 = 0000 - 44 55 44 55 | 77 66 66 66 ; a = 1010, 1 = 0001 - 55 44 55 44 | 66 77 77 77 ; 5 = 0101, e = 1110 - 55 44 55 44 | 77 77 77 77 ; 5 = 0101, f = 1111 - - I've added a dividing line in the above to clearly delineate the - quadrants. - - - Now, if P0 > P1 then we get 10 more bytes from the data stream: - - B0 B1 B2 B3 P2 P3 B4 B5 B6 B7 - - Now, if P2 <= P3, then the first six bytes [P0 P1 B0 B1 B2 B3] - represent the left half of the block and the latter six bytes - [P2 P3 B4 B5 B6 B7] represent the right half. - - For example: - - 22 00 01 37 f7 31 11 66 8c e6 73 31 - - yeilds: - - 22 22 22 22 | 11 11 11 66 ; 0: 0000 | 8: 1000 - 00 22 22 22 | 11 11 66 66 ; 1: 0001 | C: 1100 - 00 00 22 22 | 11 66 66 66 ; 3: 0011 | e: 1110 - 00 00 00 22 | 11 66 11 66 ; 7: 0111 | 6: 0101 - 00 00 00 00 | 66 66 66 11 ; f: 1111 | 7: 0111 - 00 00 00 22 | 66 66 11 11 ; 7: 0111 | 3: 0011 - 00 00 22 22 | 66 66 11 11 ; 3: 0011 | 3: 0011 - 00 22 22 22 | 66 11 11 11 ; 1: 0001 | 1: 0001 - - - On the other hand, if P0 > P1 and P2 > P3, then - [P0 P1 B0 B1 B2 B3] represent the top half of the - block and [P2 P3 B4 B5 B6 B7] represent the bottom half. - - For example: - - 22 00 cc 66 33 19 66 11 18 24 42 81 - - yeilds: - - 22 22 00 00 22 22 00 00 ; cc: 11001100 - 22 00 00 22 22 00 00 22 ; 66: 01100110 - 00 00 22 22 00 00 22 22 ; 33: 00110011 - 00 22 22 00 00 22 22 22 ; 19: 00011001 - ----------------------- - 66 66 66 11 11 66 66 66 ; 18: 00011000 - 66 66 11 66 66 11 66 66 ; 24: 00100100 - 66 11 66 66 66 66 11 66 ; 42: 01000010 - 11 66 66 66 66 66 66 11 ; 81: 10000001 - */ - if ( (*pData)[0] <= (*pData)[1]) - { - // four quadrant case - for (i=0; i<4; i++) - { - p[0] = *(*pData)++; - p[1] = *(*pData)++; - pat[0] = *(*pData)++; - pat[1] = *(*pData)++; - patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); - - // alternate between moving down and moving up and right - if (i & 1) - *pFrame += 4 - 4*g_width; // up and right - else - *pFrame += 4*g_width; // down - } - } - else if ( (*pData)[6] <= (*pData)[7]) - { - // split horizontal - for (i=0; i<4; i++) - { - if ((i & 1) == 0) - { - p[0] = *(*pData)++; - p[1] = *(*pData)++; - } - pat[0] = *(*pData)++; - pat[1] = *(*pData)++; - patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); - - if (i & 1) - *pFrame -= (4*g_width - 4); - else - *pFrame += 4*g_width; - } - } - else - { - // split vertical - for (i=0; i<8; i++) - { - if ((i & 3) == 0) - { - p[0] = *(*pData)++; - p[1] = *(*pData)++; - } - patternRow2Pixels(*pFrame, *(*pData)++, p); - *pFrame += g_width; - } - *pFrame -= (8*g_width - 8); - } - break; - - case 0x9: - /* Similar to the previous 2 encodings, only more complicated. And - it will get worse before it gets better. No longer are we dealing - with patterns over two pixel values. Now we are dealing with - patterns over 4 pixel values with 2 bits assigned to each pixel - (or block of pixels). - - So, first on the data stream are our 4 pixel values: - - P0 P1 P2 P3 - - Now, if P0 <= P1 AND P2 <= P3, we get 16 bytes of pattern, each - 2 bits representing a 1x1 pixel (00=P0, 01=P1, 10=P2, 11=P3). The - ordering is again left to right and top to bottom. The most - significant bits represent the left side at the top, and so on. - - If P0 <= P1 AND P2 > P3, we get 4 bytes of pattern, each 2 bits - representing a 2x2 pixel. Ordering is left to right and top to - bottom. - - if P0 > P1 AND P2 <= P3, we get 8 bytes of pattern, each 2 bits - representing a 2x1 pixel (i.e. 2 pixels wide, and 1 high). - - if P0 > P1 AND P2 > P3, we get 8 bytes of pattern, each 2 bits - representing a 1x2 pixel (i.e. 1 pixel wide, and 2 high). - */ - if ( (*pData)[0] <= (*pData)[1]) - { - if ( (*pData)[2] <= (*pData)[3]) - { - p[0] = *(*pData)++; - p[1] = *(*pData)++; - p[2] = *(*pData)++; - p[3] = *(*pData)++; - - for (i=0; i<8; i++) - { - pat[0] = *(*pData)++; - pat[1] = *(*pData)++; - patternRow4Pixels(*pFrame, pat[0], pat[1], p); - *pFrame += g_width; - } - - *pFrame -= (8*g_width - 8); - } - else - { - p[0] = *(*pData)++; - p[1] = *(*pData)++; - p[2] = *(*pData)++; - p[3] = *(*pData)++; - - patternRow4Pixels2(*pFrame, *(*pData)++, p); - *pFrame += 2*g_width; - patternRow4Pixels2(*pFrame, *(*pData)++, p); - *pFrame += 2*g_width; - patternRow4Pixels2(*pFrame, *(*pData)++, p); - *pFrame += 2*g_width; - patternRow4Pixels2(*pFrame, *(*pData)++, p); - *pFrame -= (6*g_width - 8); - } - } - else - { - if ( (*pData)[2] <= (*pData)[3]) - { - // draw 2x1 strips - p[0] = *(*pData)++; - p[1] = *(*pData)++; - p[2] = *(*pData)++; - p[3] = *(*pData)++; - - for (i=0; i<8; i++) - { - pat[0] = *(*pData)++; - patternRow4Pixels2x1(*pFrame, pat[0], p); - *pFrame += g_width; - } - - *pFrame -= (8*g_width - 8); - } - else - { - // draw 1x2 strips - p[0] = *(*pData)++; - p[1] = *(*pData)++; - p[2] = *(*pData)++; - p[3] = *(*pData)++; - - for (i=0; i<4; i++) - { - pat[0] = *(*pData)++; - pat[1] = *(*pData)++; - patternRow4Pixels(*pFrame, pat[0], pat[1], p); - *pFrame += g_width; - patternRow4Pixels(*pFrame, pat[0], pat[1], p); - *pFrame += g_width; - } - - *pFrame -= (8*g_width - 8); - } - } - break; - - case 0xa: - /* Similar to the previous, only a little more complicated. - - We are still dealing with patterns over 4 pixel values with 2 bits - assigned to each pixel (or block of pixels). - - So, first on the data stream are our 4 pixel values: - - P0 P1 P2 P3 - - Now, if P0 <= P1, the block is divided into 4 quadrants, ordered - (as with opcode 0x8) TL, BL, TR, BR. In this case the next data - in the data stream should be: - - B0 B1 B2 B3 - P4 P5 P6 P7 B4 B5 B6 B7 - P8 P9 P10 P11 B8 B9 B10 B11 - P12 P13 P14 P15 B12 B13 B14 B15 - - Each 2 bits represent a 1x1 pixel (00=P0, 01=P1, 10=P2, 11=P3). - The ordering is again left to right and top to bottom. The most - significant bits represent the right side at the top, and so on. - - If P0 > P1 then the next data on the data stream is: - - B0 B1 B2 B3 B4 B5 B6 B7 - P4 P5 P6 P7 B8 B9 B10 B11 B12 B13 B14 B15 - - Now, in this case, if P4 <= P5, - [P0 P1 P2 P3 B0 B1 B2 B3 B4 B5 B6 B7] represent the left half of - the block and the other bytes represent the right half. If P4 > - P5, then [P0 P1 P2 P3 B0 B1 B2 B3 B4 B5 B6 B7] represent the top - half of the block and the other bytes represent the bottom half. - */ - if ( (*pData)[0] <= (*pData)[1]) - { - for (i=0; i<4; i++) - { - p[0] = *(*pData)++; - p[1] = *(*pData)++; - p[2] = *(*pData)++; - p[3] = *(*pData)++; - pat[0] = *(*pData)++; - pat[1] = *(*pData)++; - pat[2] = *(*pData)++; - pat[3] = *(*pData)++; - - patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); - - if (i & 1) - *pFrame -= (4*g_width - 4); - else - *pFrame += 4*g_width; - } - } - else - { - if ( (*pData)[12] <= (*pData)[13]) - { - // split vertical - for (i=0; i<4; i++) - { - if ((i&1) == 0) - { - p[0] = *(*pData)++; - p[1] = *(*pData)++; - p[2] = *(*pData)++; - p[3] = *(*pData)++; - } - - pat[0] = *(*pData)++; - pat[1] = *(*pData)++; - pat[2] = *(*pData)++; - pat[3] = *(*pData)++; - - patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); - - if (i & 1) - *pFrame -= (4*g_width - 4); - else - *pFrame += 4*g_width; - } - } - else - { - // split horizontal - for (i=0; i<8; i++) - { - if ((i&3) == 0) - { - p[0] = *(*pData)++; - p[1] = *(*pData)++; - p[2] = *(*pData)++; - p[3] = *(*pData)++; - } - - pat[0] = *(*pData)++; - pat[1] = *(*pData)++; - patternRow4Pixels(*pFrame, pat[0], pat[1], p); - *pFrame += g_width; - } - - *pFrame -= (8*g_width - 8); - } - } - break; - - case 0xb: - /* In this encoding we get raw pixel data in the data stream -- 64 - bytes of pixel data. 1 byte for each pixel, and in the standard - order (l->r, t->b). - */ - for (i=0; i<8; i++) - { - memcpy(*pFrame, *pData, 8); - *pFrame += g_width; - *pData += 8; - *pDataRemain -= 8; - } - *pFrame -= (8*g_width - 8); - break; - - case 0xc: - /* In this encoding we get raw pixel data in the data stream -- 16 - bytes of pixel data. 1 byte for each block of 2x2 pixels, and in - the standard order (l->r, t->b). - */ - for (i=0; i<4; i++) - { - for (j=0; j<2; j++) - { - for (k=0; k<4; k++) - { - (*pFrame)[2*k] = (*pData)[k]; - (*pFrame)[2*k+1] = (*pData)[k]; - } - *pFrame += g_width; - } - *pData += 4; - *pDataRemain -= 4; - } - *pFrame -= (8*g_width - 8); - break; - - case 0xd: - /* In this encoding we get raw pixel data in the data stream -- 4 - bytes of pixel data. 1 byte for each block of 4x4 pixels, and in - the standard order (l->r, t->b). - */ - for (i=0; i<2; i++) - { - for (j=0; j<4; j++) - { - for (k=0; k<4; k++) - { - (*pFrame)[k*g_width+j] = (*pData)[0]; - (*pFrame)[k*g_width+j+4] = (*pData)[1]; - } - } - *pFrame += 4*g_width; - *pData += 2; - *pDataRemain -= 2; - } - *pFrame -= (8*g_width - 8); - break; - - case 0xe: - /* This encoding represents a solid 8x8 frame. We get 1 byte of pixel - data from the data stream. - */ - for (i=0; i<8; i++) - { - memset(*pFrame, **pData, 8); - *pFrame += g_width; - } - ++*pData; - --*pDataRemain; - *pFrame -= (8*g_width - 8); - break; - - case 0xf: - /* This encoding represents a "dithered" frame, which is - checkerboarded with alternate pixels of two colors. We get 2 - bytes of pixel data from the data stream, and these bytes are - alternated: - - P0 P1 P0 P1 P0 P1 P0 P1 - P1 P0 P1 P0 P1 P0 P1 P0 - ... - P0 P1 P0 P1 P0 P1 P0 P1 - P1 P0 P1 P0 P1 P0 P1 P0 - */ - for (i=0; i<8; i++) - { - for (j=0; j<8; j++) - { - (*pFrame)[j] = (*pData)[(i+j)&1]; - } - *pFrame += g_width; - } - *pData += 2; - *pDataRemain -= 2; - *pFrame -= (8*g_width - 8); - break; - - default: - break; - } +static void dispatchDecoder(unsigned char **pFrame, unsigned char codeType, unsigned char **pData, int *pDataRemain, + int *curXb, int *curYb) { + unsigned char p[4]; + unsigned char pat[16]; + int i, j, k; + int x, y; + + /* Data is processed in 8x8 pixel blocks. + There are 16 ways to encode each block. + */ + + switch (codeType) { + case 0x0: + /* block is copied from block in current frame */ + copyFrame(*pFrame, *pFrame + ((unsigned char *)g_vBackBuf2 - (unsigned char *)g_vBackBuf1)); + case 0x1: + /* block is unchanged from two frames ago */ + *pFrame += 8; + break; + + case 0x2: + /* Block is copied from nearby (below and/or to the right) within the + new frame. The offset within the buffer from which to grab the + patch of 8 pixels is given by grabbing a byte B from the data + stream, which is broken into a positive x and y offset according + to the following mapping: + + if B < 56: + x = 8 + (B % 7) + y = B / 7 + else + x = -14 + ((B - 56) % 29) + y = 8 + ((B - 56) / 29) + */ + relFar(*(*pData)++, 1, &x, &y); + copyFrame(*pFrame, *pFrame + x + y * g_width); + *pFrame += 8; + --*pDataRemain; + break; + + case 0x3: + /* Block is copied from nearby (above and/or to the left) within the + new frame. + + if B < 56: + x = -(8 + (B % 7)) + y = -(B / 7) + else + x = -(-14 + ((B - 56) % 29)) + y = -( 8 + ((B - 56) / 29)) + */ + relFar(*(*pData)++, -1, &x, &y); + copyFrame(*pFrame, *pFrame + x + y * g_width); + *pFrame += 8; + --*pDataRemain; + break; + + case 0x4: + /* Similar to 0x2 and 0x3, except this method copies from the + "current" frame, rather than the "new" frame, and instead of the + lopsided mapping they use, this one uses one which is symmetric + and centered around the top-left corner of the block. This uses + only 1 byte still, though, so the range is decreased, since we + have to encode all directions in a single byte. The byte we pull + from the data stream, I'll call B. Call the highest 4 bits of B + BH and the lowest 4 bytes BL. Then the offset from which to copy + the data is: + + x = -8 + BL + y = -8 + BH + */ + relClose(*(*pData)++, &x, &y); + copyFrame(*pFrame, *pFrame + ((unsigned char *)g_vBackBuf2 - (unsigned char *)g_vBackBuf1) + x + y * g_width); + *pFrame += 8; + --*pDataRemain; + break; + + case 0x5: + /* Similar to 0x4, but instead of one byte for the offset, this uses + two bytes to encode a larger range, the first being the x offset + as a signed 8-bit value, and the second being the y offset as a + signed 8-bit value. + */ + x = (signed char)*(*pData)++; + y = (signed char)*(*pData)++; + copyFrame(*pFrame, *pFrame + ((unsigned char *)g_vBackBuf2 - (unsigned char *)g_vBackBuf1) + x + y * g_width); + *pFrame += 8; + *pDataRemain -= 2; + break; + + case 0x6: + /* I can't figure out how any file containing a block of this type + could still be playable, since it appears that it would leave the + internal bookkeeping in an inconsistent state in the BG player + code. Ahh, well. Perhaps it was a bug in the BG player code that + just didn't happen to be exposed by any of the included movies. + Anyway, this skips the next two blocks, doing nothing to them. + Note that if you've reached the end of a row, this means going on + to the next row. + */ + for (i = 0; i < 2; i++) { + *pFrame += 16; + if (++*curXb == (g_width >> 3)) { + *pFrame += 7 * g_width; + *curXb = 0; + if (++*curYb == (g_height >> 3)) + return; + } + } + break; + + case 0x7: + /* Ok, here's where it starts to get really...interesting. This is, + incidentally, the part where they started using self-modifying + code. So, most of the following encodings are "patterned" blocks, + where we are given a number of pixel values and then bitmapped + values to specify which pixel values belong to which squares. For + this encoding, we are given the following in the data stream: + + P0 P1 + + These are pixel values (i.e. 8-bit indices into the palette). If + P0 <= P1, we then get 8 more bytes from the data stream, one for + each row in the block: + + B0 B1 B2 B3 B4 B5 B6 B7 + + For each row, the leftmost pixel is represented by the low-order + bit, and the rightmost by the high-order bit. Use your imagination + in between. If a bit is set, the pixel value is P1 and if it is + unset, the pixel value is P0. + + So, for example, if we had: + + 11 22 fe 83 83 83 83 83 83 fe + + This would represent the following layout: + + 11 22 22 22 22 22 22 22 ; fe == 11111110 + 22 22 11 11 11 11 11 22 ; 83 == 10000011 + 22 22 11 11 11 11 11 22 ; 83 == 10000011 + 22 22 11 11 11 11 11 22 ; 83 == 10000011 + 22 22 11 11 11 11 11 22 ; 83 == 10000011 + 22 22 11 11 11 11 11 22 ; 83 == 10000011 + 22 22 11 11 11 11 11 22 ; 83 == 10000011 + 11 22 22 22 22 22 22 22 ; fe == 11111110 + + If, on the other hand, P0 > P1, we get two more bytes from the + data stream: + + B0 B1 + + Each of these bytes contains two 4-bit patterns. These patterns + work like the patterns above with 8 bytes, except each bit + represents a 2x2 pixel region. + + B0 contains the pattern for the top two rows and B1 contains + the pattern for the bottom two rows. Note that the low-order + nibble of each byte contains the pattern for the upper of the + two rows that that byte controls. + + So if we had: + + 22 11 7e 83 + + The output would be: + + 11 11 22 22 22 22 22 22 ; e == 1 1 1 0 + 11 11 22 22 22 22 22 22 ; + 22 22 22 22 22 22 11 11 ; 7 == 0 1 1 1 + 22 22 22 22 22 22 11 11 ; + 11 11 11 11 11 11 22 22 ; 3 == 1 0 0 0 + 11 11 11 11 11 11 22 22 ; + 22 22 22 22 11 11 11 11 ; 8 == 0 0 1 1 + 22 22 22 22 11 11 11 11 ; + */ + p[0] = *(*pData)++; + p[1] = *(*pData)++; + if (p[0] <= p[1]) { + for (i = 0; i < 8; i++) { + patternRow2Pixels(*pFrame, *(*pData)++, p); + *pFrame += g_width; + } + } else { + for (i = 0; i < 2; i++) { + patternRow2Pixels2(*pFrame, *(*pData) & 0xf, p); + *pFrame += 2 * g_width; + patternRow2Pixels2(*pFrame, *(*pData)++ >> 4, p); + *pFrame += 2 * g_width; + } + } + *pFrame -= (8 * g_width - 8); + break; + + case 0x8: + /* Ok, this one is basically like encoding 0x7, only more + complicated. Again, we start out by getting two bytes on the data + stream: + + P0 P1 + + if P0 <= P1 then we get the following from the data stream: + + B0 B1 + P2 P3 B2 B3 + P4 P5 B4 B5 + P6 P7 B6 B7 + + P0 P1 and B0 B1 are used for the top-left corner, P2 P3 B2 B3 for + the bottom-left corner, P4 P5 B4 B5 for the top-right, P6 P7 B6 B7 + for the bottom-right. (So, each codes for a 4x4 pixel array.) + Since we have 16 bits in B0 B1, there is one bit for each pixel in + the array. The convention for the bit-mapping is, again, left to + right and top to bottom. + + So, basically, the top-left quarter of the block is an arbitrary + pattern with 2 pixels, the bottom-left a different arbitrary + pattern with 2 different pixels, and so on. + + For example if the next 16 bytes were: + + 00 22 f9 9f 44 55 aa 55 11 33 cc 33 66 77 01 ef + + We'd draw: + + 22 22 22 22 | 11 11 33 33 ; f = 1111, c = 1100 + 22 00 00 22 | 11 11 33 33 ; 9 = 1001, c = 1100 + 22 00 00 22 | 33 33 11 11 ; 9 = 1001, 3 = 0011 + 22 22 22 22 | 33 33 11 11 ; f = 1111, 3 = 0011 + ------------+------------ + 44 55 44 55 | 66 66 66 66 ; a = 1010, 0 = 0000 + 44 55 44 55 | 77 66 66 66 ; a = 1010, 1 = 0001 + 55 44 55 44 | 66 77 77 77 ; 5 = 0101, e = 1110 + 55 44 55 44 | 77 77 77 77 ; 5 = 0101, f = 1111 + + I've added a dividing line in the above to clearly delineate the + quadrants. + + + Now, if P0 > P1 then we get 10 more bytes from the data stream: + + B0 B1 B2 B3 P2 P3 B4 B5 B6 B7 + + Now, if P2 <= P3, then the first six bytes [P0 P1 B0 B1 B2 B3] + represent the left half of the block and the latter six bytes + [P2 P3 B4 B5 B6 B7] represent the right half. + + For example: + + 22 00 01 37 f7 31 11 66 8c e6 73 31 + + yeilds: + + 22 22 22 22 | 11 11 11 66 ; 0: 0000 | 8: 1000 + 00 22 22 22 | 11 11 66 66 ; 1: 0001 | C: 1100 + 00 00 22 22 | 11 66 66 66 ; 3: 0011 | e: 1110 + 00 00 00 22 | 11 66 11 66 ; 7: 0111 | 6: 0101 + 00 00 00 00 | 66 66 66 11 ; f: 1111 | 7: 0111 + 00 00 00 22 | 66 66 11 11 ; 7: 0111 | 3: 0011 + 00 00 22 22 | 66 66 11 11 ; 3: 0011 | 3: 0011 + 00 22 22 22 | 66 11 11 11 ; 1: 0001 | 1: 0001 + + + On the other hand, if P0 > P1 and P2 > P3, then + [P0 P1 B0 B1 B2 B3] represent the top half of the + block and [P2 P3 B4 B5 B6 B7] represent the bottom half. + + For example: + + 22 00 cc 66 33 19 66 11 18 24 42 81 + + yeilds: + + 22 22 00 00 22 22 00 00 ; cc: 11001100 + 22 00 00 22 22 00 00 22 ; 66: 01100110 + 00 00 22 22 00 00 22 22 ; 33: 00110011 + 00 22 22 00 00 22 22 22 ; 19: 00011001 + ----------------------- + 66 66 66 11 11 66 66 66 ; 18: 00011000 + 66 66 11 66 66 11 66 66 ; 24: 00100100 + 66 11 66 66 66 66 11 66 ; 42: 01000010 + 11 66 66 66 66 66 66 11 ; 81: 10000001 + */ + if ((*pData)[0] <= (*pData)[1]) { + // four quadrant case + for (i = 0; i < 4; i++) { + p[0] = *(*pData)++; + p[1] = *(*pData)++; + pat[0] = *(*pData)++; + pat[1] = *(*pData)++; + patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); + + // alternate between moving down and moving up and right + if (i & 1) + *pFrame += 4 - 4 * g_width; // up and right + else + *pFrame += 4 * g_width; // down + } + } else if ((*pData)[6] <= (*pData)[7]) { + // split horizontal + for (i = 0; i < 4; i++) { + if ((i & 1) == 0) { + p[0] = *(*pData)++; + p[1] = *(*pData)++; + } + pat[0] = *(*pData)++; + pat[1] = *(*pData)++; + patternQuadrant2Pixels(*pFrame, pat[0], pat[1], p); + + if (i & 1) + *pFrame -= (4 * g_width - 4); + else + *pFrame += 4 * g_width; + } + } else { + // split vertical + for (i = 0; i < 8; i++) { + if ((i & 3) == 0) { + p[0] = *(*pData)++; + p[1] = *(*pData)++; + } + patternRow2Pixels(*pFrame, *(*pData)++, p); + *pFrame += g_width; + } + *pFrame -= (8 * g_width - 8); + } + break; + + case 0x9: + /* Similar to the previous 2 encodings, only more complicated. And + it will get worse before it gets better. No longer are we dealing + with patterns over two pixel values. Now we are dealing with + patterns over 4 pixel values with 2 bits assigned to each pixel + (or block of pixels). + + So, first on the data stream are our 4 pixel values: + + P0 P1 P2 P3 + + Now, if P0 <= P1 AND P2 <= P3, we get 16 bytes of pattern, each + 2 bits representing a 1x1 pixel (00=P0, 01=P1, 10=P2, 11=P3). The + ordering is again left to right and top to bottom. The most + significant bits represent the left side at the top, and so on. + + If P0 <= P1 AND P2 > P3, we get 4 bytes of pattern, each 2 bits + representing a 2x2 pixel. Ordering is left to right and top to + bottom. + + if P0 > P1 AND P2 <= P3, we get 8 bytes of pattern, each 2 bits + representing a 2x1 pixel (i.e. 2 pixels wide, and 1 high). + + if P0 > P1 AND P2 > P3, we get 8 bytes of pattern, each 2 bits + representing a 1x2 pixel (i.e. 1 pixel wide, and 2 high). + */ + if ((*pData)[0] <= (*pData)[1]) { + if ((*pData)[2] <= (*pData)[3]) { + p[0] = *(*pData)++; + p[1] = *(*pData)++; + p[2] = *(*pData)++; + p[3] = *(*pData)++; + + for (i = 0; i < 8; i++) { + pat[0] = *(*pData)++; + pat[1] = *(*pData)++; + patternRow4Pixels(*pFrame, pat[0], pat[1], p); + *pFrame += g_width; + } + + *pFrame -= (8 * g_width - 8); + } else { + p[0] = *(*pData)++; + p[1] = *(*pData)++; + p[2] = *(*pData)++; + p[3] = *(*pData)++; + + patternRow4Pixels2(*pFrame, *(*pData)++, p); + *pFrame += 2 * g_width; + patternRow4Pixels2(*pFrame, *(*pData)++, p); + *pFrame += 2 * g_width; + patternRow4Pixels2(*pFrame, *(*pData)++, p); + *pFrame += 2 * g_width; + patternRow4Pixels2(*pFrame, *(*pData)++, p); + *pFrame -= (6 * g_width - 8); + } + } else { + if ((*pData)[2] <= (*pData)[3]) { + // draw 2x1 strips + p[0] = *(*pData)++; + p[1] = *(*pData)++; + p[2] = *(*pData)++; + p[3] = *(*pData)++; + + for (i = 0; i < 8; i++) { + pat[0] = *(*pData)++; + patternRow4Pixels2x1(*pFrame, pat[0], p); + *pFrame += g_width; + } + + *pFrame -= (8 * g_width - 8); + } else { + // draw 1x2 strips + p[0] = *(*pData)++; + p[1] = *(*pData)++; + p[2] = *(*pData)++; + p[3] = *(*pData)++; + + for (i = 0; i < 4; i++) { + pat[0] = *(*pData)++; + pat[1] = *(*pData)++; + patternRow4Pixels(*pFrame, pat[0], pat[1], p); + *pFrame += g_width; + patternRow4Pixels(*pFrame, pat[0], pat[1], p); + *pFrame += g_width; + } + + *pFrame -= (8 * g_width - 8); + } + } + break; + + case 0xa: + /* Similar to the previous, only a little more complicated. + + We are still dealing with patterns over 4 pixel values with 2 bits + assigned to each pixel (or block of pixels). + + So, first on the data stream are our 4 pixel values: + + P0 P1 P2 P3 + + Now, if P0 <= P1, the block is divided into 4 quadrants, ordered + (as with opcode 0x8) TL, BL, TR, BR. In this case the next data + in the data stream should be: + + B0 B1 B2 B3 + P4 P5 P6 P7 B4 B5 B6 B7 + P8 P9 P10 P11 B8 B9 B10 B11 + P12 P13 P14 P15 B12 B13 B14 B15 + + Each 2 bits represent a 1x1 pixel (00=P0, 01=P1, 10=P2, 11=P3). + The ordering is again left to right and top to bottom. The most + significant bits represent the right side at the top, and so on. + + If P0 > P1 then the next data on the data stream is: + + B0 B1 B2 B3 B4 B5 B6 B7 + P4 P5 P6 P7 B8 B9 B10 B11 B12 B13 B14 B15 + + Now, in this case, if P4 <= P5, + [P0 P1 P2 P3 B0 B1 B2 B3 B4 B5 B6 B7] represent the left half of + the block and the other bytes represent the right half. If P4 > + P5, then [P0 P1 P2 P3 B0 B1 B2 B3 B4 B5 B6 B7] represent the top + half of the block and the other bytes represent the bottom half. + */ + if ((*pData)[0] <= (*pData)[1]) { + for (i = 0; i < 4; i++) { + p[0] = *(*pData)++; + p[1] = *(*pData)++; + p[2] = *(*pData)++; + p[3] = *(*pData)++; + pat[0] = *(*pData)++; + pat[1] = *(*pData)++; + pat[2] = *(*pData)++; + pat[3] = *(*pData)++; + + patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); + + if (i & 1) + *pFrame -= (4 * g_width - 4); + else + *pFrame += 4 * g_width; + } + } else { + if ((*pData)[12] <= (*pData)[13]) { + // split vertical + for (i = 0; i < 4; i++) { + if ((i & 1) == 0) { + p[0] = *(*pData)++; + p[1] = *(*pData)++; + p[2] = *(*pData)++; + p[3] = *(*pData)++; + } + + pat[0] = *(*pData)++; + pat[1] = *(*pData)++; + pat[2] = *(*pData)++; + pat[3] = *(*pData)++; + + patternQuadrant4Pixels(*pFrame, pat[0], pat[1], pat[2], pat[3], p); + + if (i & 1) + *pFrame -= (4 * g_width - 4); + else + *pFrame += 4 * g_width; + } + } else { + // split horizontal + for (i = 0; i < 8; i++) { + if ((i & 3) == 0) { + p[0] = *(*pData)++; + p[1] = *(*pData)++; + p[2] = *(*pData)++; + p[3] = *(*pData)++; + } + + pat[0] = *(*pData)++; + pat[1] = *(*pData)++; + patternRow4Pixels(*pFrame, pat[0], pat[1], p); + *pFrame += g_width; + } + + *pFrame -= (8 * g_width - 8); + } + } + break; + + case 0xb: + /* In this encoding we get raw pixel data in the data stream -- 64 + bytes of pixel data. 1 byte for each pixel, and in the standard + order (l->r, t->b). + */ + for (i = 0; i < 8; i++) { + memcpy(*pFrame, *pData, 8); + *pFrame += g_width; + *pData += 8; + *pDataRemain -= 8; + } + *pFrame -= (8 * g_width - 8); + break; + + case 0xc: + /* In this encoding we get raw pixel data in the data stream -- 16 + bytes of pixel data. 1 byte for each block of 2x2 pixels, and in + the standard order (l->r, t->b). + */ + for (i = 0; i < 4; i++) { + for (j = 0; j < 2; j++) { + for (k = 0; k < 4; k++) { + (*pFrame)[2 * k] = (*pData)[k]; + (*pFrame)[2 * k + 1] = (*pData)[k]; + } + *pFrame += g_width; + } + *pData += 4; + *pDataRemain -= 4; + } + *pFrame -= (8 * g_width - 8); + break; + + case 0xd: + /* In this encoding we get raw pixel data in the data stream -- 4 + bytes of pixel data. 1 byte for each block of 4x4 pixels, and in + the standard order (l->r, t->b). + */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 4; j++) { + for (k = 0; k < 4; k++) { + (*pFrame)[k * g_width + j] = (*pData)[0]; + (*pFrame)[k * g_width + j + 4] = (*pData)[1]; + } + } + *pFrame += 4 * g_width; + *pData += 2; + *pDataRemain -= 2; + } + *pFrame -= (8 * g_width - 8); + break; + + case 0xe: + /* This encoding represents a solid 8x8 frame. We get 1 byte of pixel + data from the data stream. + */ + for (i = 0; i < 8; i++) { + memset(*pFrame, **pData, 8); + *pFrame += g_width; + } + ++*pData; + --*pDataRemain; + *pFrame -= (8 * g_width - 8); + break; + + case 0xf: + /* This encoding represents a "dithered" frame, which is + checkerboarded with alternate pixels of two colors. We get 2 + bytes of pixel data from the data stream, and these bytes are + alternated: + + P0 P1 P0 P1 P0 P1 P0 P1 + P1 P0 P1 P0 P1 P0 P1 P0 + ... + P0 P1 P0 P1 P0 P1 P0 P1 + P1 P0 P1 P0 P1 P0 P1 P0 + */ + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + (*pFrame)[j] = (*pData)[(i + j) & 1]; + } + *pFrame += g_width; + } + *pData += 2; + *pDataRemain -= 2; + *pFrame -= (8 * g_width - 8); + break; + + default: + break; + } } diff --git a/libmve/decoders.h b/libmve/decoders.h index 9cff2f25..725f910c 100644 --- a/libmve/decoders.h +++ b/libmve/decoders.h @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2002-2024 D2X Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + /* * * INTERNAL header - not to be included outside of libmve @@ -10,7 +27,9 @@ extern int g_width, g_height; extern void *g_vBackBuf1, *g_vBackBuf2; -extern void decodeFrame8(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain); -extern void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, int dataRemain); +extern void decodeFrame8(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, + int dataRemain); +extern void decodeFrame16(unsigned char *pFrame, unsigned char *pMap, int mapRemain, unsigned char *pData, + int dataRemain); #endif // _DECODERS_H diff --git a/libmve/libmve.h b/libmve/libmve.h index 15895e9e..ea97ed88 100644 --- a/libmve/libmve.h +++ b/libmve/libmve.h @@ -1,18 +1,35 @@ +/* + * Copyright (C) 2002-2024 D2X Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef _LIBMVE_H #define _LIBMVE_H #define MVE_ERR_EOF 1 -typedef struct{ - int screenWidth; - int screenHeight; - int width; - int height; - int truecolor; +typedef struct { + int screenWidth; + int screenHeight; + int width; + int height; + int truecolor; } MVE_videoSpec; -int MVE_rmPrepMovie(void *stream, int x, int y, int track); -int MVE_rmStepMovie(void); +int MVE_rmPrepMovie(void *stream, int x, int y, int track); +int MVE_rmStepMovie(void); void MVE_rmHoldMovie(void); void MVE_rmEndMovie(void); @@ -20,21 +37,15 @@ void MVE_getVideoSpec(MVE_videoSpec *vSpec); void MVE_sndInit(int x); -typedef unsigned int (*mve_cb_Read)(void *stream, - void *buffer, - unsigned int count); +typedef unsigned int (*mve_cb_Read)(void *stream, void *buffer, unsigned int count); typedef void *(*mve_cb_Alloc)(unsigned int size); typedef void (*mve_cb_Free)(void *ptr); -typedef void (*mve_cb_ShowFrame)(unsigned char *buffer, - unsigned int bufw, unsigned int bufh, - unsigned int sx, unsigned int sy, - unsigned int w, unsigned int h, - unsigned int dstx, unsigned int dsty); +typedef void (*mve_cb_ShowFrame)(unsigned char *buffer, unsigned int bufw, unsigned int bufh, unsigned int sx, + unsigned int sy, unsigned int w, unsigned int h, unsigned int dstx, unsigned int dsty); -typedef void (*mve_cb_SetPalette)(unsigned char *p, - unsigned int start, unsigned int count); +typedef void (*mve_cb_SetPalette)(unsigned char *p, unsigned int start, unsigned int count); void MVE_ioCallbacks(mve_cb_Read io_read); void MVE_memCallbacks(mve_cb_Alloc mem_alloc, mve_cb_Free mem_free); diff --git a/libmve/mve_audio.c b/libmve/mve_audio.c index 4495a035..89a1fa74 100644 --- a/libmve/mve_audio.c +++ b/libmve/mve_audio.c @@ -1,55 +1,80 @@ -static int audio_exp_table[256] = -{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 47, 51, 56, 61, - 66, 72, 79, 86, 94, 102, 112, 122, 133, 145, 158, 173, 189, 206, 225, 245, - 267, 292, 318, 348, 379, 414, 452, 493, 538, 587, 640, 699, 763, 832, 908, 991, - 1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993, 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008, - 4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059, 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206, - 17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589, -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1, - 1, 1, 5481, 10503, 15105, 19322, 23186, 26728, 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298, - -17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597, -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772, - -4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373, -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180, - -1081, -991, -908, -832, -763, -699, -640, -587, -538, -493, -452, -414, -379, -348, -318, -292, - -267, -245, -225, -206, -189, -173, -158, -145, -133, -122, -112, -102, -94, -86, -79, -72, - -66, -61, -56, -51, -47, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33, - -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, - -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1 +/* + * Copyright (C) 2002-2024 D2X Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +static int audio_exp_table[256] = { + 0, 1, 2, 3, 4, 5, 6, 7, // 8 + 8, 9, 10, 11, 12, 13, 14, 15, // + 16, 17, 18, 19, 20, 21, 22, 23, // + 24, 25, 26, 27, 28, 29, 30, 31, // + 32, 33, 34, 35, 36, 37, 38, 39, // + 40, 41, 42, 43, 47, 51, 56, 61, // + 66, 72, 79, 86, 94, 102, 112, 122, // + 133, 145, 158, 173, 189, 206, 225, 245, // 64 + 267, 292, 318, 348, 379, 414, 452, 493, // + 538, 587, 640, 699, 763, 832, 908, 991, // + 1081, 1180, 1288, 1405, 1534, 1673, 1826, 1993, // + 2175, 2373, 2590, 2826, 3084, 3365, 3672, 4008, // + 4373, 4772, 5208, 5683, 6202, 6767, 7385, 8059, // + 8794, 9597, 10472, 11428, 12471, 13609, 14851, 16206, // + 17685, 19298, 21060, 22981, 25078, 27367, 29864, 32589, // + -29973, -26728, -23186, -19322, -15105, -10503, -5481, -1, // 128 + 1, 1, 5481, 10503, 15105, 19322, 23186, 26728, // + 29973, -32589, -29864, -27367, -25078, -22981, -21060, -19298, // + -17685, -16206, -14851, -13609, -12471, -11428, -10472, -9597, // + -8794, -8059, -7385, -6767, -6202, -5683, -5208, -4772, // + -4373, -4008, -3672, -3365, -3084, -2826, -2590, -2373, // + -2175, -1993, -1826, -1673, -1534, -1405, -1288, -1180, // + -1081, -991, -908, -832, -763, -699, -640, -587, // + -538, -493, -452, -414, -379, -348, -318, -292, // 196 + -267, -245, -225, -206, -189, -173, -158, -145, // + -133, -122, -112, -102, -94, -86, -79, -72, // + -66, -61, -56, -51, -47, -43, -42, -41, // + -40, -39, -38, -37, -36, -35, -34, -33, // + -32, -31, -30, -29, -28, -27, -26, -25, // + -24, -23, -22, -21, -20, -19, -18, -17, // + -16, -15, -14, -13, -12, -11, -10, -9, // + -8, -7, -6, -5, -4, -3, -2, -1, // 256 }; -static int getWord(unsigned char **fin) -{ - int value = ((*fin)[1] << 8) | (*fin)[0]; - *fin += 2; - return value; +static int getWord(unsigned char **fin) { + int value = ((*fin)[1] << 8) | (*fin)[0]; + *fin += 2; + return value; } -static void sendWord(short **fout, int nOffset) -{ - *(*fout)++ = nOffset; +static void sendWord(short **fout, int nOffset) { *(*fout)++ = nOffset; } + +static void processSwath(short *fout, unsigned char *data, int swath, int *offsets) { + int i; + for (i = 0; i < swath; i++) { + offsets[i & 1] += audio_exp_table[data[i]]; + sendWord(&fout, offsets[i & 1]); + } } -static void processSwath(short *fout, unsigned char *data, int swath, int *offsets) -{ - int i; - for (i=0; i. + */ + #ifndef INCLUDED_MVE_AUDIO_H #define INCLUDED_MVE_AUDIO_H diff --git a/libmve/mvelib.c b/libmve/mvelib.c index cdc4eb86..987c962b 100644 --- a/libmve/mvelib.c +++ b/libmve/mvelib.c @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2002-2024 D2X Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifdef HAVE_CONFIG_H #include "conf.h" #endif @@ -12,7 +29,7 @@ #include "mvelib.h" -static const char MVE_HEADER[] = "Interplay MVE File\x1A"; +static const char MVE_HEADER[] = "Interplay MVE File\x1A"; static const short MVE_HDRCONST1 = 0x001A; static const short MVE_HDRCONST2 = 0x0100; static const short MVE_HDRCONST3 = 0x1133; @@ -36,7 +53,7 @@ static MVEFILE *_mvefile_alloc(void); static void _mvefile_free(MVEFILE *movie); static int _mvefile_open(MVEFILE *movie, void *stream); static void _mvefile_reset(MVEFILE *movie); -static int _mvefile_read_header(MVEFILE *movie); +static int _mvefile_read_header(MVEFILE *movie); static void _mvefile_set_buffer_size(MVEFILE *movie, int buf_size); static int _mvefile_fetch_next_chunk(MVEFILE *movie); @@ -55,157 +72,140 @@ static void _mvestream_reset(MVESTREAM *movie); /* * open an MVE file */ -MVEFILE *mvefile_open(void *stream) -{ - MVEFILE *file; +MVEFILE *mvefile_open(void *stream) { + MVEFILE *file; - /* create the file */ - file = _mvefile_alloc(); - if (! _mvefile_open(file, stream)) - { - _mvefile_free(file); - return NULL; - } + /* create the file */ + file = _mvefile_alloc(); + if (!_mvefile_open(file, stream)) { + _mvefile_free(file); + return NULL; + } - /* initialize the file */ - _mvefile_set_buffer_size(file, 1024); + /* initialize the file */ + _mvefile_set_buffer_size(file, 1024); - /* verify the file's header */ - if (! _mvefile_read_header(file)) - { - _mvefile_free(file); - return NULL; - } + /* verify the file's header */ + if (!_mvefile_read_header(file)) { + _mvefile_free(file); + return NULL; + } - /* now, prefetch the next chunk */ - _mvefile_fetch_next_chunk(file); + /* now, prefetch the next chunk */ + _mvefile_fetch_next_chunk(file); - return file; + return file; } /* * close a MVE file */ -void mvefile_close(MVEFILE *movie) -{ - _mvefile_free(movie); -} +void mvefile_close(MVEFILE *movie) { _mvefile_free(movie); } /* * reset a MVE file */ -void mvefile_reset(MVEFILE *file) -{ - _mvefile_reset(file); +void mvefile_reset(MVEFILE *file) { + _mvefile_reset(file); - /* initialize the file */ - _mvefile_set_buffer_size(file, 1024); + /* initialize the file */ + _mvefile_set_buffer_size(file, 1024); - /* verify the file's header */ - if (! _mvefile_read_header(file)) - { - _mvefile_free(file); - //return NULL; - } + /* verify the file's header */ + if (!_mvefile_read_header(file)) { + _mvefile_free(file); + // return NULL; + } - /* now, prefetch the next chunk */ - _mvefile_fetch_next_chunk(file); + /* now, prefetch the next chunk */ + _mvefile_fetch_next_chunk(file); } /* * get the size of the next segment */ -int mvefile_get_next_segment_size(MVEFILE *movie) -{ - /* if nothing is cached, fail */ - if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) - return -1; +int mvefile_get_next_segment_size(MVEFILE *movie) { + /* if nothing is cached, fail */ + if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) + return -1; - /* if we don't have enough data to get a segment, fail */ - if (movie->cur_fill - movie->next_segment < 4) - return -1; + /* if we don't have enough data to get a segment, fail */ + if (movie->cur_fill - movie->next_segment < 4) + return -1; - /* otherwise, get the data length */ - return _mve_get_short(movie->cur_chunk + movie->next_segment); + /* otherwise, get the data length */ + return _mve_get_short(movie->cur_chunk + movie->next_segment); } /* * get type of next segment in chunk (0xff if no more segments in chunk) */ -unsigned char mvefile_get_next_segment_major(MVEFILE *movie) -{ - /* if nothing is cached, fail */ - if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) - return 0xff; +unsigned char mvefile_get_next_segment_major(MVEFILE *movie) { + /* if nothing is cached, fail */ + if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) + return 0xff; - /* if we don't have enough data to get a segment, fail */ - if (movie->cur_fill - movie->next_segment < 4) - return 0xff; + /* if we don't have enough data to get a segment, fail */ + if (movie->cur_fill - movie->next_segment < 4) + return 0xff; - /* otherwise, get the data length */ - return movie->cur_chunk[movie->next_segment + 2]; + /* otherwise, get the data length */ + return movie->cur_chunk[movie->next_segment + 2]; } /* * get subtype (version) of next segment in chunk (0xff if no more segments in * chunk) */ -unsigned char mvefile_get_next_segment_minor(MVEFILE *movie) -{ - /* if nothing is cached, fail */ - if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) - return 0xff; +unsigned char mvefile_get_next_segment_minor(MVEFILE *movie) { + /* if nothing is cached, fail */ + if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) + return 0xff; - /* if we don't have enough data to get a segment, fail */ - if (movie->cur_fill - movie->next_segment < 4) - return 0xff; + /* if we don't have enough data to get a segment, fail */ + if (movie->cur_fill - movie->next_segment < 4) + return 0xff; - /* otherwise, get the data length */ - return movie->cur_chunk[movie->next_segment + 3]; + /* otherwise, get the data length */ + return movie->cur_chunk[movie->next_segment + 3]; } /* * see next segment (return NULL if no next segment) */ -unsigned char *mvefile_get_next_segment(MVEFILE *movie) -{ - /* if nothing is cached, fail */ - if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) - return NULL; +unsigned char *mvefile_get_next_segment(MVEFILE *movie) { + /* if nothing is cached, fail */ + if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) + return NULL; - /* if we don't have enough data to get a segment, fail */ - if (movie->cur_fill - movie->next_segment < 4) - return NULL; + /* if we don't have enough data to get a segment, fail */ + if (movie->cur_fill - movie->next_segment < 4) + return NULL; - /* otherwise, get the data length */ - return movie->cur_chunk + movie->next_segment + 4; + /* otherwise, get the data length */ + return movie->cur_chunk + movie->next_segment + 4; } /* * advance to next segment */ -void mvefile_advance_segment(MVEFILE *movie) -{ - /* if nothing is cached, fail */ - if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) - return; +void mvefile_advance_segment(MVEFILE *movie) { + /* if nothing is cached, fail */ + if (movie->cur_chunk == NULL || movie->next_segment >= movie->cur_fill) + return; - /* if we don't have enough data to get a segment, fail */ - if (movie->cur_fill - movie->next_segment < 4) - return; + /* if we don't have enough data to get a segment, fail */ + if (movie->cur_fill - movie->next_segment < 4) + return; - /* else, advance to next segment */ - movie->next_segment += - (4 + _mve_get_ushort(movie->cur_chunk + movie->next_segment)); + /* else, advance to next segment */ + movie->next_segment += (4 + _mve_get_ushort(movie->cur_chunk + movie->next_segment)); } /* * fetch the next chunk (return 0 if at end of stream) */ -int mvefile_fetch_next_chunk(MVEFILE *movie) -{ - return _mvefile_fetch_next_chunk(movie); -} +int mvefile_fetch_next_chunk(MVEFILE *movie) { return _mvefile_fetch_next_chunk(movie); } /************************************************************ * public MVESTREAM functions @@ -214,90 +214,75 @@ int mvefile_fetch_next_chunk(MVEFILE *movie) /* * open an MVE stream */ -MVESTREAM *mve_open(void *stream) -{ - MVESTREAM *movie; +MVESTREAM *mve_open(void *stream) { + MVESTREAM *movie; - /* allocate */ - movie = _mvestream_alloc(); + /* allocate */ + movie = _mvestream_alloc(); - /* open */ - if (! _mvestream_open(movie, stream)) - { - _mvestream_free(movie); - return NULL; - } + /* open */ + if (!_mvestream_open(movie, stream)) { + _mvestream_free(movie); + return NULL; + } - return movie; + return movie; } /* * close an MVE stream */ -void mve_close(MVESTREAM *movie) -{ - _mvestream_free(movie); -} +void mve_close(MVESTREAM *movie) { _mvestream_free(movie); } /* * reset an MVE stream */ -void mve_reset(MVESTREAM *movie) -{ - _mvestream_reset(movie); -} +void mve_reset(MVESTREAM *movie) { _mvestream_reset(movie); } /* * set segment type handler */ -void mve_set_handler(MVESTREAM *movie, unsigned char major, MVESEGMENTHANDLER handler) -{ - if (major < 32) - movie->handlers[major] = handler; +void mve_set_handler(MVESTREAM *movie, unsigned char major, MVESEGMENTHANDLER handler) { + if (major < 32) + movie->handlers[major] = handler; } /* * set segment handler context */ -void mve_set_handler_context(MVESTREAM *movie, void *context) -{ - movie->context = context; -} +void mve_set_handler_context(MVESTREAM *movie, void *context) { movie->context = context; } /* * play next chunk */ -int mve_play_next_chunk(MVESTREAM *movie) -{ - unsigned char major, minor; - unsigned char *data; - int len; +int mve_play_next_chunk(MVESTREAM *movie) { + unsigned char major, minor; + unsigned char *data; + int len; - /* loop over segments */ - major = mvefile_get_next_segment_major(movie->movie); - while (major != 0xff) - { - /* check whether to handle the segment */ - if (major < 32 && movie->handlers[major] != NULL) - { - minor = mvefile_get_next_segment_minor(movie->movie); - len = mvefile_get_next_segment_size(movie->movie); - data = mvefile_get_next_segment(movie->movie); + /* loop over segments */ + major = mvefile_get_next_segment_major(movie->movie); + while (major != 0xff) { + /* check whether to handle the segment */ + if (major < 32 && movie->handlers[major] != NULL) { + minor = mvefile_get_next_segment_minor(movie->movie); + len = mvefile_get_next_segment_size(movie->movie); + data = mvefile_get_next_segment(movie->movie); - if (! movie->handlers[major](major, minor, data, len, movie->context)) - return 0; - } - - /* advance to next segment */ - mvefile_advance_segment(movie->movie); - major = mvefile_get_next_segment_major(movie->movie); + if (!movie->handlers[major](major, minor, data, len, movie->context)) + return 0; } - if (! mvefile_fetch_next_chunk(movie->movie)) - return 0; + /* advance to next segment */ + mvefile_advance_segment(movie->movie); + major = mvefile_get_next_segment_major(movie->movie); + } - /* return status */ - return 1; + if (!mvefile_fetch_next_chunk(movie->movie)) + return 0; + + /* return status */ + return 1; } /************************************************************ @@ -307,57 +292,53 @@ int mve_play_next_chunk(MVESTREAM *movie) /* * allocate an MVEFILE */ -static MVEFILE *_mvefile_alloc(void) -{ - MVEFILE *file = (MVEFILE *)mve_alloc(sizeof(MVEFILE)); - file->stream = NULL; - file->cur_chunk = NULL; - file->buf_size = 0; - file->cur_fill = 0; - file->next_segment = 0; +static MVEFILE *_mvefile_alloc(void) { + MVEFILE *file = (MVEFILE *)mve_alloc(sizeof(MVEFILE)); + file->stream = NULL; + file->cur_chunk = NULL; + file->buf_size = 0; + file->cur_fill = 0; + file->next_segment = 0; - return file; + return file; } /* * free an MVE file */ -static void _mvefile_free(MVEFILE *movie) -{ - /* free the stream */ - movie->stream = NULL; +static void _mvefile_free(MVEFILE *movie) { + /* free the stream */ + movie->stream = NULL; - /* free the buffer */ - if (movie->cur_chunk) - mve_free(movie->cur_chunk); - movie->cur_chunk = NULL; + /* free the buffer */ + if (movie->cur_chunk) + mve_free(movie->cur_chunk); + movie->cur_chunk = NULL; - /* not strictly necessary */ - movie->buf_size = 0; - movie->cur_fill = 0; - movie->next_segment = 0; + /* not strictly necessary */ + movie->buf_size = 0; + movie->cur_fill = 0; + movie->next_segment = 0; - /* free the struct */ - mve_free(movie); + /* free the struct */ + mve_free(movie); } /* * open the file stream in thie object */ -static int _mvefile_open(MVEFILE *file, void *stream) -{ - file->stream = stream; - if (! file->stream) - return 0; +static int _mvefile_open(MVEFILE *file, void *stream) { + file->stream = stream; + if (!file->stream) + return 0; - return 1; + return 1; } /* * allocate an MVEFILE */ -static void _mvefile_reset(MVEFILE *file) -{ +static void _mvefile_reset(MVEFILE *file) { #if 0 file->cur_chunk = NULL; file->buf_size = 0; @@ -369,152 +350,140 @@ static void _mvefile_reset(MVEFILE *file) /* * read and verify the header of the recently opened file */ -static int _mvefile_read_header(MVEFILE *movie) -{ - unsigned char buffer[26]; +static int _mvefile_read_header(MVEFILE *movie) { + unsigned char buffer[26]; - /* check the file is open */ - if (! movie->stream) - return 0; + /* check the file is open */ + if (!movie->stream) + return 0; - /* check the file is long enough */ - if (! mve_read(movie->stream, buffer, 26)) - return 0; + /* check the file is long enough */ + if (!mve_read(movie->stream, buffer, 26)) + return 0; - /* check the signature */ - if (memcmp(buffer, MVE_HEADER, 20)) - return 0; + /* check the signature */ + if (memcmp(buffer, MVE_HEADER, 20)) + return 0; - /* check the hard-coded constants */ - if (_mve_get_short(buffer+20) != MVE_HDRCONST1) - return 0; - if (_mve_get_short(buffer+22) != MVE_HDRCONST2) - return 0; - if (_mve_get_short(buffer+24) != MVE_HDRCONST3) - return 0; + /* check the hard-coded constants */ + if (_mve_get_short(buffer + 20) != MVE_HDRCONST1) + return 0; + if (_mve_get_short(buffer + 22) != MVE_HDRCONST2) + return 0; + if (_mve_get_short(buffer + 24) != MVE_HDRCONST3) + return 0; - return 1; + return 1; } -static void _mvefile_set_buffer_size(MVEFILE *movie, int buf_size) -{ - unsigned char *new_buffer; - int new_len; +static void _mvefile_set_buffer_size(MVEFILE *movie, int buf_size) { + unsigned char *new_buffer; + int new_len; - /* check if this would be a redundant operation */ - if (buf_size <= movie->buf_size) - return; + /* check if this would be a redundant operation */ + if (buf_size <= movie->buf_size) + return; - /* allocate new buffer */ - new_len = 100 + buf_size; - new_buffer = (unsigned char *)mve_alloc(new_len); + /* allocate new buffer */ + new_len = 100 + buf_size; + new_buffer = (unsigned char *)mve_alloc(new_len); - /* copy old data */ - if (movie->cur_chunk && movie->cur_fill) - memcpy(new_buffer, movie->cur_chunk, movie->cur_fill); + /* copy old data */ + if (movie->cur_chunk && movie->cur_fill) + memcpy(new_buffer, movie->cur_chunk, movie->cur_fill); - /* free old buffer */ - if (movie->cur_chunk) - { - mve_free(movie->cur_chunk); - movie->cur_chunk = 0; - } + /* free old buffer */ + if (movie->cur_chunk) { + mve_free(movie->cur_chunk); + movie->cur_chunk = 0; + } - /* install new buffer */ - movie->cur_chunk = new_buffer; - movie->buf_size = new_len; + /* install new buffer */ + movie->cur_chunk = new_buffer; + movie->buf_size = new_len; } -static int _mvefile_fetch_next_chunk(MVEFILE *movie) -{ - unsigned char buffer[4]; - unsigned short length; +static int _mvefile_fetch_next_chunk(MVEFILE *movie) { + unsigned char buffer[4]; + unsigned short length; - /* fail if not open */ - if (! movie->stream) - return 0; + /* fail if not open */ + if (!movie->stream) + return 0; - /* fail if we can't read the next segment descriptor */ - if (! mve_read(movie->stream, buffer, 4)) - return 0; + /* fail if we can't read the next segment descriptor */ + if (!mve_read(movie->stream, buffer, 4)) + return 0; - /* pull out the next length */ - length = _mve_get_short(buffer); + /* pull out the next length */ + length = _mve_get_short(buffer); - /* make sure we've got sufficient space */ - _mvefile_set_buffer_size(movie, length); + /* make sure we've got sufficient space */ + _mvefile_set_buffer_size(movie, length); - /* read the chunk */ - if (! mve_read(movie->stream, movie->cur_chunk, length)) - return 0; - movie->cur_fill = length; - movie->next_segment = 0; + /* read the chunk */ + if (!mve_read(movie->stream, movie->cur_chunk, length)) + return 0; + movie->cur_fill = length; + movie->next_segment = 0; - return 1; + return 1; } -static short _mve_get_short(unsigned char *data) -{ - short value; - value = data[0] | (data[1] << 8); - return value; +static short _mve_get_short(unsigned char *data) { + short value; + value = data[0] | (data[1] << 8); + return value; } -static unsigned short _mve_get_ushort(unsigned char *data) -{ - unsigned short value; - value = data[0] | (data[1] << 8); - return value; +static unsigned short _mve_get_ushort(unsigned char *data) { + unsigned short value; + value = data[0] | (data[1] << 8); + return value; } /* * allocate an MVESTREAM */ -static MVESTREAM *_mvestream_alloc(void) -{ - MVESTREAM *movie; +static MVESTREAM *_mvestream_alloc(void) { + MVESTREAM *movie; - /* allocate and zero-initialize everything */ - movie = (MVESTREAM *)mve_alloc(sizeof(MVESTREAM)); - movie->movie = NULL; - movie->context = 0; - memset(movie->handlers, 0, sizeof(movie->handlers)); + /* allocate and zero-initialize everything */ + movie = (MVESTREAM *)mve_alloc(sizeof(MVESTREAM)); + movie->movie = NULL; + movie->context = 0; + memset(movie->handlers, 0, sizeof(movie->handlers)); - return movie; + return movie; } /* * free an MVESTREAM */ -static void _mvestream_free(MVESTREAM *movie) -{ - /* close MVEFILE */ - if (movie->movie) - mvefile_close(movie->movie); - movie->movie = NULL; +static void _mvestream_free(MVESTREAM *movie) { + /* close MVEFILE */ + if (movie->movie) + mvefile_close(movie->movie); + movie->movie = NULL; - /* clear context and handlers */ - movie->context = NULL; - memset(movie->handlers, 0, sizeof(movie->handlers)); + /* clear context and handlers */ + movie->context = NULL; + memset(movie->handlers, 0, sizeof(movie->handlers)); - /* free the struct */ - mve_free(movie); + /* free the struct */ + mve_free(movie); } /* * open an MVESTREAM object */ -static int _mvestream_open(MVESTREAM *movie, void *stream) -{ - movie->movie = mvefile_open(stream); +static int _mvestream_open(MVESTREAM *movie, void *stream) { + movie->movie = mvefile_open(stream); - return (movie->movie == NULL) ? 0 : 1; + return (movie->movie == NULL) ? 0 : 1; } /* * reset an MVESTREAM */ -static void _mvestream_reset(MVESTREAM *movie) -{ - mvefile_reset(movie->movie); -} +static void _mvestream_reset(MVESTREAM *movie) { mvefile_reset(movie->movie); } diff --git a/libmve/mvelib.h b/libmve/mvelib.h index 720dd001..fa74932e 100644 --- a/libmve/mvelib.h +++ b/libmve/mvelib.h @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2002-2024 D2X Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifndef INCLUDED_MVELIB_H #define INCLUDED_MVELIB_H @@ -15,13 +32,12 @@ extern mve_cb_SetPalette mve_setpalette; /* * structure for maintaining info on a MVEFILE stream */ -typedef struct MVEFILE -{ - void *stream; - unsigned char *cur_chunk; - int buf_size; - int cur_fill; - int next_segment; +typedef struct MVEFILE { + void *stream; + unsigned char *cur_chunk; + int buf_size; + int cur_fill; + int next_segment; } MVEFILE; /* @@ -73,11 +89,10 @@ typedef int (*MVESEGMENTHANDLER)(unsigned char major, unsigned char minor, unsig /* * structure for maintaining an MVE stream */ -typedef struct MVESTREAM -{ - MVEFILE *movie; - void *context; - MVESEGMENTHANDLER handlers[32]; +typedef struct MVESTREAM { + MVEFILE *movie; + void *context; + MVESEGMENTHANDLER handlers[32]; } MVESTREAM; /* diff --git a/libmve/mveplay.c b/libmve/mveplay.c index 7be40090..9a533d86 100644 --- a/libmve/mveplay.c +++ b/libmve/mveplay.c @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2002-2024 D2X Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + #ifdef HAVE_CONFIG_H #include #endif @@ -5,24 +22,24 @@ #ifndef __MSDOS__ #define AUDIO #endif -//#define DEBUG +// #define DEBUG #include #ifdef _WIN32 -# include +#include #else -# include -# include -# include -# ifdef macintosh -# include -# include -# else -# include -# include -# include -# include -# endif // macintosh +#include +#include +#include +#ifdef macintosh +#include +#include +#else +#include +#include +#include +#include +#endif // macintosh #endif // _WIN32 #if defined(AUDIO) @@ -37,70 +54,64 @@ #include "libmve.h" -#define MVE_OPCODE_ENDOFSTREAM 0x00 -#define MVE_OPCODE_ENDOFCHUNK 0x01 -#define MVE_OPCODE_CREATETIMER 0x02 -#define MVE_OPCODE_INITAUDIOBUFFERS 0x03 -#define MVE_OPCODE_STARTSTOPAUDIO 0x04 -#define MVE_OPCODE_INITVIDEOBUFFERS 0x05 +#define MVE_OPCODE_ENDOFSTREAM 0x00 +#define MVE_OPCODE_ENDOFCHUNK 0x01 +#define MVE_OPCODE_CREATETIMER 0x02 +#define MVE_OPCODE_INITAUDIOBUFFERS 0x03 +#define MVE_OPCODE_STARTSTOPAUDIO 0x04 +#define MVE_OPCODE_INITVIDEOBUFFERS 0x05 -#define MVE_OPCODE_DISPLAYVIDEO 0x07 -#define MVE_OPCODE_AUDIOFRAMEDATA 0x08 -#define MVE_OPCODE_AUDIOFRAMESILENCE 0x09 -#define MVE_OPCODE_INITVIDEOMODE 0x0A +#define MVE_OPCODE_DISPLAYVIDEO 0x07 +#define MVE_OPCODE_AUDIOFRAMEDATA 0x08 +#define MVE_OPCODE_AUDIOFRAMESILENCE 0x09 +#define MVE_OPCODE_INITVIDEOMODE 0x0A -#define MVE_OPCODE_SETPALETTE 0x0C +#define MVE_OPCODE_SETPALETTE 0x0C #define MVE_OPCODE_SETPALETTECOMPRESSED 0x0D -#define MVE_OPCODE_SETDECODINGMAP 0x0F +#define MVE_OPCODE_SETDECODINGMAP 0x0F -#define MVE_OPCODE_VIDEODATA 0x11 +#define MVE_OPCODE_VIDEODATA 0x11 -#define MVE_AUDIO_FLAGS_STEREO 1 -#define MVE_AUDIO_FLAGS_16BIT 2 +#define MVE_AUDIO_FLAGS_STEREO 1 +#define MVE_AUDIO_FLAGS_16BIT 2 #define MVE_AUDIO_FLAGS_COMPRESSED 4 -int g_spdFactorNum=0; -static int g_spdFactorDenom=10; +int g_spdFactorNum = 0; +static int g_spdFactorDenom = 10; static int g_frameUpdated = 0; -static short get_short(unsigned char *data) -{ - short value; - value = data[0] | (data[1] << 8); - return value; +static short get_short(unsigned char *data) { + short value; + value = data[0] | (data[1] << 8); + return value; } -static unsigned short get_ushort(unsigned char *data) -{ - unsigned short value; - value = data[0] | (data[1] << 8); - return value; +static unsigned short get_ushort(unsigned char *data) { + unsigned short value; + value = data[0] | (data[1] << 8); + return value; } -static int get_int(unsigned char *data) -{ - int value; - value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); - return value; +static int get_int(unsigned char *data) { + int value; + value = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); + return value; } -static unsigned int unhandled_chunks[32*256]; +static unsigned int unhandled_chunks[32 * 256]; -static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ - unhandled_chunks[major<<8|minor]++; - //fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor); - return 1; +static int default_seg_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { + unhandled_chunks[major << 8 | minor]++; + // fprintf(stderr, "unknown chunk type %02x/%02x\n", major, minor); + return 1; } - /************************* * general handlers *************************/ -static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ - return 0; +static int end_movie_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { + return 0; } /************************* @@ -111,113 +122,105 @@ static int end_movie_handler(unsigned char major, unsigned char minor, unsigned * timer variables */ static int timer_created = 0; -static int micro_frame_delay=0; -static int timer_started=0; +static int micro_frame_delay = 0; +static int timer_started = 0; static unsigned long int timer_expire = 0; #if defined(_WIN32) || defined(macintosh) -unsigned long int timer_getmicroseconds() -{ - static int counter = 0; +unsigned long int timer_getmicroseconds() { + static int counter = 0; #ifdef _WIN32 - DWORD now = GetTickCount(); + DWORD now = GetTickCount(); #else - long now = TickCount(); + long now = TickCount(); #endif - counter++; + counter++; - return now * 1000 + counter; + return now * 1000 + counter; } #else -unsigned long int timer_getmicroseconds() -{ - struct timeval tv; - static time_t starttime = 0; +unsigned long int timer_getmicroseconds() { + struct timeval tv; + static time_t starttime = 0; - gettimeofday(&tv, NULL); + gettimeofday(&tv, NULL); - if (!starttime) - starttime = tv.tv_sec; + if (!starttime) + starttime = tv.tv_sec; - return (tv.tv_sec - starttime) * 1000000 + tv.tv_usec; + return (tv.tv_sec - starttime) * 1000000 + tv.tv_usec; } #endif -void timer_sleepmicroseconds(unsigned long int usec) -{ +void timer_sleepmicroseconds(unsigned long int usec) { #ifdef _WIN32 - Sleep(usec / 1000); + Sleep(usec / 1000); #elif defined(macintosh) - Delay(usec / 1000); + Delay(usec / 1000); #else - struct timespec ts; - ts.tv_sec = usec / 1000000; - ts.tv_nsec = usec % 1000000 * 1000; - nanosleep(&ts, NULL); + struct timespec ts; + ts.tv_sec = usec / 1000000; + ts.tv_nsec = usec % 1000000 * 1000; + nanosleep(&ts, NULL); #endif } -static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ +static int create_timer_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { #if !defined(_WIN32) && !defined(macintosh) // FIXME - __extension__ long long temp; + __extension__ long long temp; #else - long temp; + long temp; #endif - if (timer_created) - return 1; - else - timer_created = 1; + if (timer_created) + return 1; + else + timer_created = 1; - micro_frame_delay = get_int(data) * (int)get_short(data+4); - if (g_spdFactorNum != 0) - { - temp = micro_frame_delay; - temp *= g_spdFactorNum; - temp /= g_spdFactorDenom; - micro_frame_delay = (int)temp; - } + micro_frame_delay = get_int(data) * (int)get_short(data + 4); + if (g_spdFactorNum != 0) { + temp = micro_frame_delay; + temp *= g_spdFactorNum; + temp /= g_spdFactorDenom; + micro_frame_delay = (int)temp; + } - return 1; + return 1; } -static void timer_stop(void) -{ - timer_expire = 0; - timer_started = 0; +static void timer_stop(void) { + timer_expire = 0; + timer_started = 0; } -static void timer_start(void) -{ - timer_expire = timer_getmicroseconds(); - timer_expire += micro_frame_delay; - timer_started=1; +static void timer_start(void) { + timer_expire = timer_getmicroseconds(); + timer_expire += micro_frame_delay; + timer_started = 1; } -static void do_timer_wait(void) -{ - unsigned long int ts; - unsigned long int tv; +static void do_timer_wait(void) { + unsigned long int ts; + unsigned long int tv; - if (! timer_started) - return; + if (!timer_started) + return; - tv = timer_getmicroseconds(); - if (tv > timer_expire) - goto end; + tv = timer_getmicroseconds(); + if (tv > timer_expire) + goto end; - ts = timer_expire - tv; + ts = timer_expire - tv; - timer_sleepmicroseconds(ts); + timer_sleepmicroseconds(ts); - end: - timer_expire += micro_frame_delay; +end: + timer_expire += micro_frame_delay; } /************************* @@ -229,203 +232,194 @@ static void do_timer_wait(void) static int audiobuf_created = 0; static void mve_audio_callback(void *userdata, unsigned char *stream, int len); static short *mve_audio_buffers[TOTAL_AUDIO_BUFFERS]; -static int mve_audio_buflens[TOTAL_AUDIO_BUFFERS]; -static int mve_audio_curbuf_curpos=0; -static int mve_audio_bufhead=0; -static int mve_audio_buftail=0; -static int mve_audio_playing=0; -static int mve_audio_canplay=0; -static int mve_audio_compressed=0; +static int mve_audio_buflens[TOTAL_AUDIO_BUFFERS]; +static int mve_audio_curbuf_curpos = 0; +static int mve_audio_bufhead = 0; +static int mve_audio_buftail = 0; +static int mve_audio_playing = 0; +static int mve_audio_canplay = 0; +static int mve_audio_compressed = 0; static int mve_audio_enabled = 1; +static void mve_audio_callback(void *userdata, unsigned char *stream, int len) { + int total = 0; + int length; + if (mve_audio_bufhead == mve_audio_buftail) + return /* 0 */; -static void mve_audio_callback(void *userdata, unsigned char *stream, int len) -{ - int total=0; - int length; - if (mve_audio_bufhead == mve_audio_buftail) - return /* 0 */; + // fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len); - //fprintf(stderr, "+ <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len); + while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */ + && len > (mve_audio_buflens[mve_audio_bufhead] - mve_audio_curbuf_curpos)) /* and while we need more data */ + { + length = mve_audio_buflens[mve_audio_bufhead] - mve_audio_curbuf_curpos; + memcpy(stream, /* cur output position */ + ((unsigned char *)mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* cur input position */ + length); /* cur input length */ - while (mve_audio_bufhead != mve_audio_buftail /* while we have more buffers */ - && len > (mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos)) /* and while we need more data */ - { - length = mve_audio_buflens[mve_audio_bufhead]-mve_audio_curbuf_curpos; - memcpy(stream, /* cur output position */ - ((unsigned char *)mve_audio_buffers[mve_audio_bufhead])+mve_audio_curbuf_curpos, /* cur input position */ - length); /* cur input length */ + total += length; + stream += length; /* advance output */ + len -= length; /* decrement avail ospace */ + mve_free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */ + mve_audio_buffers[mve_audio_bufhead] = NULL; /* free the buffer */ + mve_audio_buflens[mve_audio_bufhead] = 0; /* free the buffer */ - total += length; - stream += length; /* advance output */ - len -= length; /* decrement avail ospace */ - mve_free(mve_audio_buffers[mve_audio_bufhead]); /* free the buffer */ - mve_audio_buffers[mve_audio_bufhead]=NULL; /* free the buffer */ - mve_audio_buflens[mve_audio_bufhead]=0; /* free the buffer */ + if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */ + mve_audio_bufhead = 0; + mve_audio_curbuf_curpos = 0; + } - if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */ - mve_audio_bufhead = 0; - mve_audio_curbuf_curpos = 0; - } + // fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, + // total); + /* return total; */ - //fprintf(stderr, "= <%d (%d), %d, %d>: %d\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len, total); - /* return total; */ + if (len != 0 /* ospace remaining */ + && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */ + { + memcpy(stream, /* dest */ + ((unsigned char *)mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* src */ + len); /* length */ - if (len != 0 /* ospace remaining */ - && mve_audio_bufhead != mve_audio_buftail) /* buffers remaining */ - { - memcpy(stream, /* dest */ - ((unsigned char *)mve_audio_buffers[mve_audio_bufhead]) + mve_audio_curbuf_curpos, /* src */ - len); /* length */ + mve_audio_curbuf_curpos += len; /* advance input */ + stream += len; /* advance output (unnecessary) */ + len -= len; /* advance output (unnecessary) */ - mve_audio_curbuf_curpos += len; /* advance input */ - stream += len; /* advance output (unnecessary) */ - len -= len; /* advance output (unnecessary) */ + if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */ + { + mve_free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */ + mve_audio_buffers[mve_audio_bufhead] = NULL; + mve_audio_buflens[mve_audio_bufhead] = 0; - if (mve_audio_curbuf_curpos >= mve_audio_buflens[mve_audio_bufhead]) /* if this ends the current chunk */ - { - mve_free(mve_audio_buffers[mve_audio_bufhead]); /* free buffer */ - mve_audio_buffers[mve_audio_bufhead]=NULL; - mve_audio_buflens[mve_audio_bufhead]=0; + if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */ + mve_audio_bufhead = 0; + mve_audio_curbuf_curpos = 0; + } + } - if (++mve_audio_bufhead == TOTAL_AUDIO_BUFFERS) /* next buffer */ - mve_audio_bufhead = 0; - mve_audio_curbuf_curpos = 0; - } - } - - //fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len); + // fprintf(stderr, "- <%d (%d), %d, %d>\n", mve_audio_bufhead, mve_audio_curbuf_curpos, mve_audio_buftail, len); } #endif -static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ +static int create_audiobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, + void *context) { #ifdef AUDIO - int flags; - int sample_rate; - int desired_buffer; + int flags; + int sample_rate; + int desired_buffer; - int stereo; - int bitsize; - int compressed; + int stereo; + int bitsize; + int compressed; - int format; + int format; - if (!mve_audio_enabled) - return 1; + if (!mve_audio_enabled) + return 1; - if (audiobuf_created) - return 1; - else - audiobuf_created = 1; + if (audiobuf_created) + return 1; + else + audiobuf_created = 1; - flags = get_ushort(data + 2); - sample_rate = get_ushort(data + 4); - desired_buffer = get_int(data + 6); + flags = get_ushort(data + 2); + sample_rate = get_ushort(data + 4); + desired_buffer = get_int(data + 6); - stereo = (flags & MVE_AUDIO_FLAGS_STEREO) ? 1 : 0; - bitsize = (flags & MVE_AUDIO_FLAGS_16BIT) ? 1 : 0; + stereo = (flags & MVE_AUDIO_FLAGS_STEREO) ? 1 : 0; + bitsize = (flags & MVE_AUDIO_FLAGS_16BIT) ? 1 : 0; - if (minor > 0) { - compressed = flags & MVE_AUDIO_FLAGS_COMPRESSED ? 1 : 0; - } else { - compressed = 0; - } + if (minor > 0) { + compressed = flags & MVE_AUDIO_FLAGS_COMPRESSED ? 1 : 0; + } else { + compressed = 0; + } - mve_audio_compressed = compressed; + mve_audio_compressed = compressed; - if (bitsize == 1) { + if (bitsize == 1) { #ifdef WORDS_BIGENDIAN - format = AUDIO_S16MSB; + format = AUDIO_S16MSB; #else - format = AUDIO_S16LSB; + format = AUDIO_S16LSB; #endif - } else { - format = AUDIO_U8; - } + } else { + format = AUDIO_U8; + } - fprintf(stderr, "creating audio buffers:\n"); - fprintf(stderr, "sample rate = %d, stereo = %d, bitsize = %d, compressed = %d\n", - sample_rate, stereo, bitsize ? 16 : 8, compressed); + fprintf(stderr, "creating audio buffers:\n"); + fprintf(stderr, "sample rate = %d, stereo = %d, bitsize = %d, compressed = %d\n", sample_rate, stereo, + bitsize ? 16 : 8, compressed); - if (Mix_OpenAudio(sample_rate, format, stereo ? 2 : 1, 4096) == 0) - { - fprintf(stderr, " success\n"); - mve_audio_canplay = 1; - } - else - { - fprintf(stderr, " failure : %s\n", Mix_GetError()); - mve_audio_canplay = 0; - } + if (Mix_OpenAudio(sample_rate, format, stereo ? 2 : 1, 4096) == 0) { + fprintf(stderr, " success\n"); + mve_audio_canplay = 1; + } else { + fprintf(stderr, " failure : %s\n", Mix_GetError()); + mve_audio_canplay = 0; + } - Mix_SetPostMix(mve_audio_callback, NULL); - mve_audio_canplay = 1; + Mix_SetPostMix(mve_audio_callback, NULL); + mve_audio_canplay = 1; - memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers)); - memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens)); + memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers)); + memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens)); #endif - return 1; + return 1; } -static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ +static int play_audio_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { #ifdef AUDIO - if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail) - { - Mix_Resume(-1); - mve_audio_playing = 1; - } + if (mve_audio_canplay && !mve_audio_playing && mve_audio_bufhead != mve_audio_buftail) { + Mix_Resume(-1); + mve_audio_playing = 1; + } #endif - return 1; + return 1; } -static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ +static int audio_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { #ifdef AUDIO - static const int selected_chan=1; - int chan; - int nsamp; - if (mve_audio_canplay) - { - chan = get_ushort(data + 2); - nsamp = get_ushort(data + 4); - if (chan & selected_chan) - { - /* HACK: +4 mveaudio_uncompress adds 4 more bytes */ - if (major == MVE_OPCODE_AUDIOFRAMEDATA) { - if (mve_audio_compressed) { - nsamp += 4; + static const int selected_chan = 1; + int chan; + int nsamp; + if (mve_audio_canplay) { + chan = get_ushort(data + 2); + nsamp = get_ushort(data + 4); + if (chan & selected_chan) { + /* HACK: +4 mveaudio_uncompress adds 4 more bytes */ + if (major == MVE_OPCODE_AUDIOFRAMEDATA) { + if (mve_audio_compressed) { + nsamp += 4; - mve_audio_buflens[mve_audio_buftail] = nsamp; - mve_audio_buffers[mve_audio_buftail] = (short *)mve_alloc(nsamp); - mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */ - } else { - nsamp -= 8; - data += 8; + mve_audio_buflens[mve_audio_buftail] = nsamp; + mve_audio_buffers[mve_audio_buftail] = (short *)mve_alloc(nsamp); + mveaudio_uncompress(mve_audio_buffers[mve_audio_buftail], data, -1); /* XXX */ + } else { + nsamp -= 8; + data += 8; - mve_audio_buflens[mve_audio_buftail] = nsamp; - mve_audio_buffers[mve_audio_buftail] = (short *)mve_alloc(nsamp); - memcpy(mve_audio_buffers[mve_audio_buftail], data, nsamp); - } - } else { - mve_audio_buflens[mve_audio_buftail] = nsamp; - mve_audio_buffers[mve_audio_buftail] = (short *)mve_alloc(nsamp); + mve_audio_buflens[mve_audio_buftail] = nsamp; + mve_audio_buffers[mve_audio_buftail] = (short *)mve_alloc(nsamp); + memcpy(mve_audio_buffers[mve_audio_buftail], data, nsamp); + } + } else { + mve_audio_buflens[mve_audio_buftail] = nsamp; + mve_audio_buffers[mve_audio_buftail] = (short *)mve_alloc(nsamp); - memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */ - } + memset(mve_audio_buffers[mve_audio_buftail], 0, nsamp); /* XXX */ + } - if (++mve_audio_buftail == TOTAL_AUDIO_BUFFERS) - mve_audio_buftail = 0; + if (++mve_audio_buftail == TOTAL_AUDIO_BUFFERS) + mve_audio_buftail = 0; - if (mve_audio_buftail == mve_audio_bufhead) - fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead); - } - } + if (mve_audio_buftail == mve_audio_bufhead) + fprintf(stderr, "d'oh! buffer ring overrun (%d)\n", mve_audio_bufhead); + } + } #endif - return 1; + return 1; } /************************* @@ -439,311 +433,283 @@ void *g_vBuffers = NULL, *g_vBackBuf1, *g_vBackBuf2; static int g_destX, g_destY; static int g_screenWidth, g_screenHeight; -static unsigned char *g_pCurMap=NULL; -static int g_nMapLength=0; +static unsigned char *g_pCurMap = NULL; +static int g_nMapLength = 0; static int g_truecolor; -static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ - short w, h; - short count, truecolor; +static int create_videobuf_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, + void *context) { + short w, h; + short count, truecolor; - if (videobuf_created) - return 1; - else - videobuf_created = 1; + if (videobuf_created) + return 1; + else + videobuf_created = 1; - w = get_short(data); - h = get_short(data+2); + w = get_short(data); + h = get_short(data + 2); - if (minor > 0) { - count = get_short(data+4); - } else { - count = 1; - } + if (minor > 0) { + count = get_short(data + 4); + } else { + count = 1; + } - if (minor > 1) { - truecolor = get_short(data+6); - } else { - truecolor = 0; - } + if (minor > 1) { + truecolor = get_short(data + 6); + } else { + truecolor = 0; + } - g_width = w << 3; - g_height = h << 3; + g_width = w << 3; + g_height = h << 3; - /* TODO: * 4 causes crashes on some files */ - /* only malloc once */ - if (g_vBuffers == NULL) - g_vBackBuf1 = g_vBuffers = mve_alloc(g_width * g_height * 8); - if (truecolor) { - g_vBackBuf2 = (unsigned short *)g_vBackBuf1 + (g_width * g_height); - } else { - g_vBackBuf2 = (unsigned char *)g_vBackBuf1 + (g_width * g_height); - } + /* TODO: * 4 causes crashes on some files */ + /* only malloc once */ + if (g_vBuffers == NULL) + g_vBackBuf1 = g_vBuffers = mve_alloc(g_width * g_height * 8); + if (truecolor) { + g_vBackBuf2 = (unsigned short *)g_vBackBuf1 + (g_width * g_height); + } else { + g_vBackBuf2 = (unsigned char *)g_vBackBuf1 + (g_width * g_height); + } - memset(g_vBackBuf1, 0, g_width * g_height * 4); + memset(g_vBackBuf1, 0, g_width * g_height * 4); #ifdef DEBUG - fprintf(stderr, "DEBUG: w,h=%d,%d count=%d, tc=%d\n", w, h, count, truecolor); + fprintf(stderr, "DEBUG: w,h=%d,%d count=%d, tc=%d\n", w, h, count, truecolor); #endif - g_truecolor = truecolor; + g_truecolor = truecolor; - return 1; + return 1; } -static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ - if (g_destX == -1) // center it - g_destX = (g_screenWidth - g_width) >> 1; - if (g_destY == -1) // center it - g_destY = (g_screenHeight - g_height) >> 1; +static int display_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, + void *context) { + if (g_destX == -1) // center it + g_destX = (g_screenWidth - g_width) >> 1; + if (g_destY == -1) // center it + g_destY = (g_screenHeight - g_height) >> 1; - mve_showframe(g_vBackBuf1, g_width, g_height, 0, 0, - g_width, g_height, g_destX, g_destY); + mve_showframe(g_vBackBuf1, g_width, g_height, 0, 0, g_width, g_height, g_destX, g_destY); - g_frameUpdated = 1; + g_frameUpdated = 1; - return 1; + return 1; } -static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ - short width, height; +static int init_video_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { + short width, height; - if (video_initialized) - return 1; /* maybe we actually need to change width/height here? */ - else - video_initialized = 1; + if (video_initialized) + return 1; /* maybe we actually need to change width/height here? */ + else + video_initialized = 1; - width = get_short(data); - height = get_short(data+2); - g_screenWidth = width; - g_screenHeight = height; + width = get_short(data); + height = get_short(data + 2); + g_screenWidth = width; + g_screenHeight = height; - return 1; + return 1; } -static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ - short start, count; - unsigned char *p; +static int video_palette_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, + void *context) { + short start, count; + unsigned char *p; - start = get_short(data); - count = get_short(data+2); + start = get_short(data); + count = get_short(data + 2); - p = data + 4; + p = data + 4; - mve_setpalette(p - 3*start, start, count); + mve_setpalette(p - 3 * start, start, count); - return 1; + return 1; } -static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ - g_pCurMap = data; - g_nMapLength = len; - return 1; +static int video_codemap_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, + void *context) { + g_pCurMap = data; + g_nMapLength = len; + return 1; } -static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ - short nFrameHot, nFrameCold; - short nXoffset, nYoffset; - short nXsize, nYsize; - unsigned short nFlags; - unsigned char *temp; +static int video_data_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { + short nFrameHot, nFrameCold; + short nXoffset, nYoffset; + short nXsize, nYsize; + unsigned short nFlags; + unsigned char *temp; - nFrameHot = get_short(data); - nFrameCold = get_short(data+2); - nXoffset = get_short(data+4); - nYoffset = get_short(data+6); - nXsize = get_short(data+8); - nYsize = get_short(data+10); - nFlags = get_ushort(data+12); + nFrameHot = get_short(data); + nFrameCold = get_short(data + 2); + nXoffset = get_short(data + 4); + nYoffset = get_short(data + 6); + nXsize = get_short(data + 8); + nYsize = get_short(data + 10); + nFlags = get_ushort(data + 12); - if (nFlags & 1) - { - temp = (unsigned char *)g_vBackBuf1; - g_vBackBuf1 = g_vBackBuf2; - g_vBackBuf2 = temp; - } + if (nFlags & 1) { + temp = (unsigned char *)g_vBackBuf1; + g_vBackBuf1 = g_vBackBuf2; + g_vBackBuf2 = temp; + } - /* convert the frame */ - if (g_truecolor) { - decodeFrame16((unsigned char *)g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14); - } else { - decodeFrame8(g_vBackBuf1, g_pCurMap, g_nMapLength, data+14, len-14); - } + /* convert the frame */ + if (g_truecolor) { + decodeFrame16((unsigned char *)g_vBackBuf1, g_pCurMap, g_nMapLength, data + 14, len - 14); + } else { + decodeFrame8(g_vBackBuf1, g_pCurMap, g_nMapLength, data + 14, len - 14); + } - return 1; + return 1; } -static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) -{ - g_pCurMap=NULL; - return 1; +static int end_chunk_handler(unsigned char major, unsigned char minor, unsigned char *data, int len, void *context) { + g_pCurMap = NULL; + return 1; } - static MVESTREAM *mve = NULL; -void MVE_ioCallbacks(mve_cb_Read io_read) -{ - mve_read = io_read; +void MVE_ioCallbacks(mve_cb_Read io_read) { mve_read = io_read; } + +void MVE_memCallbacks(mve_cb_Alloc mem_alloc, mve_cb_Free mem_free) { + mve_alloc = mem_alloc; + mve_free = mem_free; } -void MVE_memCallbacks(mve_cb_Alloc mem_alloc, mve_cb_Free mem_free) -{ - mve_alloc = mem_alloc; - mve_free = mem_free; +void MVE_sfCallbacks(mve_cb_ShowFrame showframe) { mve_showframe = showframe; } + +void MVE_palCallbacks(mve_cb_SetPalette setpalette) { mve_setpalette = setpalette; } + +int MVE_rmPrepMovie(void *src, int x, int y, int track) { + int i; + + if (mve) { + mve_reset(mve); + return 0; + } + + mve = mve_open(src); + + if (!mve) + return 1; + + g_destX = x; + g_destY = y; + + for (i = 0; i < 32; i++) + mve_set_handler(mve, i, default_seg_handler); + + mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler); + mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler); + mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler); + mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler); + mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler); + mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler); + + mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler); + mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler); + mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler); + mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler); + + mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler); + mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, default_seg_handler); + + mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler); + + mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler); + + mve_play_next_chunk(mve); /* video initialization chunk */ + if (mve_audio_enabled) + mve_play_next_chunk(mve); /* audio initialization chunk */ + + return 0; } -void MVE_sfCallbacks(mve_cb_ShowFrame showframe) -{ - mve_showframe = showframe; +void MVE_getVideoSpec(MVE_videoSpec *vSpec) { + vSpec->screenWidth = g_screenWidth; + vSpec->screenHeight = g_screenHeight; + vSpec->width = g_width; + vSpec->height = g_height; + vSpec->truecolor = g_truecolor; } -void MVE_palCallbacks(mve_cb_SetPalette setpalette) -{ - mve_setpalette = setpalette; +int MVE_rmStepMovie() { + static int init_timer = 0; + int cont = 1; + + if (!timer_started) + timer_start(); + + while (cont && !g_frameUpdated) // make a "step" be a frame, not a chunk... + cont = mve_play_next_chunk(mve); + g_frameUpdated = 0; + + if (!cont) + return MVE_ERR_EOF; + + if (micro_frame_delay && !init_timer) { + timer_start(); + init_timer = 1; + } + + do_timer_wait(); + + return 0; } -int MVE_rmPrepMovie(void *src, int x, int y, int track) -{ - int i; - - if (mve) { - mve_reset(mve); - return 0; - } - - mve = mve_open(src); - - if (!mve) - return 1; - - g_destX = x; - g_destY = y; - - for (i = 0; i < 32; i++) - mve_set_handler(mve, i, default_seg_handler); - - mve_set_handler(mve, MVE_OPCODE_ENDOFSTREAM, end_movie_handler); - mve_set_handler(mve, MVE_OPCODE_ENDOFCHUNK, end_chunk_handler); - mve_set_handler(mve, MVE_OPCODE_CREATETIMER, create_timer_handler); - mve_set_handler(mve, MVE_OPCODE_INITAUDIOBUFFERS, create_audiobuf_handler); - mve_set_handler(mve, MVE_OPCODE_STARTSTOPAUDIO, play_audio_handler); - mve_set_handler(mve, MVE_OPCODE_INITVIDEOBUFFERS, create_videobuf_handler); - - mve_set_handler(mve, MVE_OPCODE_DISPLAYVIDEO, display_video_handler); - mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMEDATA, audio_data_handler); - mve_set_handler(mve, MVE_OPCODE_AUDIOFRAMESILENCE, audio_data_handler); - mve_set_handler(mve, MVE_OPCODE_INITVIDEOMODE, init_video_handler); - - mve_set_handler(mve, MVE_OPCODE_SETPALETTE, video_palette_handler); - mve_set_handler(mve, MVE_OPCODE_SETPALETTECOMPRESSED, default_seg_handler); - - mve_set_handler(mve, MVE_OPCODE_SETDECODINGMAP, video_codemap_handler); - - mve_set_handler(mve, MVE_OPCODE_VIDEODATA, video_data_handler); - - mve_play_next_chunk(mve); /* video initialization chunk */ - if (mve_audio_enabled) - mve_play_next_chunk(mve); /* audio initialization chunk */ - - return 0; -} - - -void MVE_getVideoSpec(MVE_videoSpec *vSpec) -{ - vSpec->screenWidth = g_screenWidth; - vSpec->screenHeight = g_screenHeight; - vSpec->width = g_width; - vSpec->height = g_height; - vSpec->truecolor = g_truecolor; -} - - -int MVE_rmStepMovie() -{ - static int init_timer=0; - int cont=1; - - if (!timer_started) - timer_start(); - - while (cont && !g_frameUpdated) // make a "step" be a frame, not a chunk... - cont = mve_play_next_chunk(mve); - g_frameUpdated = 0; - - if (!cont) - return MVE_ERR_EOF; - - if (micro_frame_delay && !init_timer) { - timer_start(); - init_timer = 1; - } - - do_timer_wait(); - - return 0; -} - -void MVE_rmEndMovie() -{ +void MVE_rmEndMovie() { #ifdef AUDIO - int i; + int i; #endif - timer_stop(); - timer_created = 0; + timer_stop(); + timer_created = 0; #ifdef AUDIO - if (mve_audio_canplay) { - // only close audio if we opened it - Mix_CloseAudio(); - mve_audio_canplay = 0; - } - for (i = 0; i < TOTAL_AUDIO_BUFFERS; i++) - if (mve_audio_buffers[i] != NULL) - mve_free(mve_audio_buffers[i]); - memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers)); - memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens)); - mve_audio_curbuf_curpos=0; - mve_audio_bufhead=0; - mve_audio_buftail=0; - mve_audio_playing=0; - mve_audio_canplay=0; - mve_audio_compressed=0; - audiobuf_created = 0; + if (mve_audio_canplay) { + // only close audio if we opened it + Mix_CloseAudio(); + mve_audio_canplay = 0; + } + for (i = 0; i < TOTAL_AUDIO_BUFFERS; i++) + if (mve_audio_buffers[i] != NULL) + mve_free(mve_audio_buffers[i]); + memset(mve_audio_buffers, 0, sizeof(mve_audio_buffers)); + memset(mve_audio_buflens, 0, sizeof(mve_audio_buflens)); + mve_audio_curbuf_curpos = 0; + mve_audio_bufhead = 0; + mve_audio_buftail = 0; + mve_audio_playing = 0; + mve_audio_canplay = 0; + mve_audio_compressed = 0; + audiobuf_created = 0; #endif - mve_free(g_vBuffers); - g_vBuffers = NULL; - g_pCurMap=NULL; - g_nMapLength=0; - videobuf_created = 0; - video_initialized = 0; + mve_free(g_vBuffers); + g_vBuffers = NULL; + g_pCurMap = NULL; + g_nMapLength = 0; + videobuf_created = 0; + video_initialized = 0; - mve_close(mve); - mve = NULL; + mve_close(mve); + mve = NULL; } +void MVE_rmHoldMovie() { timer_started = 0; } -void MVE_rmHoldMovie() -{ - timer_started = 0; -} - - -void MVE_sndInit(int x) -{ +void MVE_sndInit(int x) { #ifdef AUDIO - if (x == -1) - mve_audio_enabled = 0; - else - mve_audio_enabled = 1; + if (x == -1) + mve_audio_enabled = 0; + else + mve_audio_enabled = 1; #endif }