diff --git a/LEGO1/omni/include/mxflcpresenter.h b/LEGO1/omni/include/mxflcpresenter.h index f1e5bf82..6e5b0526 100644 --- a/LEGO1/omni/include/mxflcpresenter.h +++ b/LEGO1/omni/include/mxflcpresenter.h @@ -7,6 +7,7 @@ #include // VTABLE: LEGO1 0x100dc2c0 +// VTABLE: BETA10 0x101c1eb0 // SIZE 0x68 class MxFlcPresenter : public MxVideoPresenter { public: diff --git a/LEGO1/omni/src/video/flic.cpp b/LEGO1/omni/src/video/flic.cpp index f15f406c..cfd7541e 100644 --- a/LEGO1/omni/src/video/flic.cpp +++ b/LEGO1/omni/src/video/flic.cpp @@ -40,7 +40,7 @@ short DecodeChunks( ); void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data); void DecodeColorPackets(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data); -void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data, short p_index, WORD p_count); +void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data, short p_index, short p_count); void DecodeColors64(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data); void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader); void DecodeLC(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader); @@ -49,14 +49,18 @@ void DecodeBlack(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_d void DecodeCopy(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader); // FUNCTION: LEGO1 0x100bd530 +// FUNCTION: BETA10 0x1013dd80 void WritePixel(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, short p_column, short p_row, byte p_pixel) { - if (p_column >= 0 && p_row >= 0 && p_column < p_bitmapHeader->biWidth && p_row < p_bitmapHeader->biHeight) { - *(((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData) = p_pixel; + if (p_column < 0 || p_row < 0 || p_column >= p_bitmapHeader->biWidth || p_row >= p_bitmapHeader->biHeight) { + return; } + + *(((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData) = p_pixel; } // FUNCTION: LEGO1 0x100bd580 +// FUNCTION: BETA10 0x1013ddef void WritePixels( LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, @@ -66,51 +70,55 @@ void WritePixels( short p_count ) { - short col = p_column; + // ClampLine could modify p_column. Save the original value. + short zcol = p_column; - if (ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { - short offset = p_column - col; - BYTE* pixels = offset ? p_data + offset : p_data; - memcpy(((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData, pixels, p_count); + if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { + return; } + + short offset = p_column - zcol; + if (offset) { + p_data += offset; + } + + BYTE* dest = ((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData; + memcpy(dest, p_data, p_count); } // FUNCTION: LEGO1 0x100bd600 +// FUNCTION: BETA10 0x1013de84 int ClampLine(LPBITMAPINFOHEADER p_bitmapHeader, short& p_column, short& p_row, short& p_count) { short column = p_column; - short row = p_row; - short count = p_count; - short end = column + count; - int result; + short a_row = p_row; + short f_count = p_count; + short end = column + f_count; - if (row < 0 || p_bitmapHeader->biHeight <= row || end < 0 || p_bitmapHeader->biWidth <= column) { - result = 0; - } - else { - if (column < 0) { - count += column; - p_count = end; - p_column = 0; - } - - if (p_bitmapHeader->biWidth < end) { - count -= end - p_bitmapHeader->biWidth; - p_count = count; - } - - if (count < 0) { - result = 0; - } - else { - result = 1; - } + if (a_row < 0 || p_bitmapHeader->biHeight <= a_row || end < 0 || p_bitmapHeader->biWidth <= column) { + return 0; } - return result; + if (column < 0) { + f_count += column; + p_count = f_count; + p_column = 0; + } + + if (p_bitmapHeader->biWidth < end) { + f_count -= end - (short) p_bitmapHeader->biWidth; + p_count = f_count; + } + + if (f_count < 0) { + return 0; + } + + return 1; } // FUNCTION: LEGO1 0x100bd680 +// FUNCTION: BETA10 0x1013df77 void WritePixelRun( LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, @@ -120,18 +128,19 @@ void WritePixelRun( short p_count ) { - short col = p_column; + if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { + return; + } - if (ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { - BYTE* dst = ((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData; + BYTE* dst = ((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData; - while (--p_count >= 0) { - *dst++ = p_pixel; - } + while (--p_count >= 0) { + *dst++ = p_pixel; } } // FUNCTION: LEGO1 0x100bd6e0 +// FUNCTION: BETA10 0x1013dfee void WritePixelPairs( LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, @@ -143,22 +152,26 @@ void WritePixelPairs( { p_count <<= 1; - if (ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { - short odd = p_count & 1; - p_count >>= 1; + if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { + return; + } - WORD* dst = (WORD*) (((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData); - while (--p_count >= 0) { - *dst++ = p_pixel; - } + short is_odd = p_count & 1; + p_count >>= 1; - if (odd) { - *(BYTE*) dst = p_pixel; - } + WORD* dst = (WORD*) (((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData); + while (--p_count >= 0) { + *dst++ = p_pixel; + } + + if (is_odd) { + BYTE* dst_byte = (BYTE*) dst; + *dst_byte = p_pixel; } } // FUNCTION: LEGO1 0x100bd760 +// FUNCTION: BETA10 0x1013e097 short DecodeChunks( LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, @@ -198,6 +211,8 @@ short DecodeChunks( case FLI_CHUNK_COPY: DecodeCopy(p_bitmapHeader, p_pixelData, (BYTE*) (chunk + 1), p_flcHeader); break; + default: + break; } } @@ -205,71 +220,81 @@ short DecodeChunks( } // FUNCTION: LEGO1 0x100bd880 +// FUNCTION: BETA10 0x1013e22c void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data) { DecodeColorPackets(p_bitmapHeader, p_data); } // FUNCTION: LEGO1 0x100bd8a0 +// FUNCTION: BETA10 0x1013e24c void DecodeColorPackets(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data) { - WORD colorIndex = 0; - BYTE* colors = p_data + 2; + short colorIndex = 0; + BYTE* colors = p_data; + short* pPackets = (short*) colors; + short packets = *pPackets; + colors += 2; - for (short packet = *((short*) p_data) - 1; packet >= 0; packet--) { - colorIndex += colors[0]; - short colorCount = colors[1]; + while (--packets >= 0) { + colorIndex += *colors++; + short colorCount = *colors++; - colors++; - colors++; - - if (!colorCount) { + if (colorCount == 0) { colorCount = 256; } DecodeColorPacket(p_bitmapHeader, colors, colorIndex, colorCount); - colorIndex += colorCount; colors += colorCount * 3; + colorIndex += colorCount; } } // FUNCTION: LEGO1 0x100bd8f0 -void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data, short index, WORD p_count) +// FUNCTION: BETA10 0x1013e2f8 +void DecodeColorPacket(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data, short index, short p_count) { - BYTE* palette = (BYTE*) p_bitmapHeader + p_bitmapHeader->biSize + index * 4; + RGBQUAD* palette = (RGBQUAD*) ((BYTE*) p_bitmapHeader + p_bitmapHeader->biSize) + index; - while (p_count-- > 0) { - palette[2] = p_data[0]; - palette[1] = p_data[1]; - palette[0] = p_data[2]; + while (p_count--) { + palette->rgbRed = p_data[0]; + palette->rgbGreen = p_data[1]; + palette->rgbBlue = p_data[2]; - palette += 4; + palette++; p_data += 3; } } // FUNCTION: LEGO1 0x100bd940 +// FUNCTION: BETA10 0x1013e364 void DecodeColors64(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data) { DecodeColorPackets(p_bitmapHeader, p_data); } // FUNCTION: LEGO1 0x100bd960 +// FUNCTION: BETA10 0x1013e384 void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) { - BYTE* data = p_data; short width = p_flcHeader->width; short height = p_flcHeader->height; + BYTE* data = p_data; BYTE* offset = ((p_bitmapHeader->biWidth + 3) & -4) * (height - 1) + p_pixelData; - for (short line = height - 1; line >= 0; line--) { + short line = height; + short width2 = width; + + while (--line >= 0) { + short column = 0; data++; + char count = 0; + while ((column += count) < width2) { + count = *data++; - for (short pixel = 0; pixel < width;) { - char count = *data++; - + short i; if (count >= 0) { - for (short i = 0; i < count; i++) { + for (i = 0; i < count; i++) { *offset++ = *data; } @@ -277,12 +302,10 @@ void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_da } else { count = -count; - for (short i = 0; i < count; i++) { + for (i = 0; i < count; i++) { *offset++ = *data++; } } - - pixel += count; } offset -= (((p_bitmapHeader->biWidth + 3) & -4) + width); @@ -290,28 +313,37 @@ void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_da } // FUNCTION: LEGO1 0x100bda10 +// FUNCTION: BETA10 0x1013e4ca void DecodeLC(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) { - short row = (short) p_flcHeader->height - *((short*) p_data) - 1; - BYTE* data = p_data + 4; + short xofs = 0; + short yofs = 0; + short* word_data = (short*) p_data; + BYTE* data = (BYTE*) word_data + 4; + short row = p_flcHeader->height - (*word_data + yofs) - 1; - for (short lines = *((short*) (p_data + 2)) - 1; lines >= 0; lines--) { - WORD column = 0; + word_data++; + short lines = *word_data; + + while (--lines >= 0) { + short column = xofs; BYTE packets = *data++; - for (BYTE i = 0; i < packets; i++) { - column += *data++; + while (packets > 0) { + column += *data++; // skip byte char type = *((char*) data++); if (type < 0) { type = -type; WritePixelRun(p_bitmapHeader, p_pixelData, column, row, *data++, type); column += type; + packets = packets - 1; } else { WritePixels(p_bitmapHeader, p_pixelData, column, row, data, type); data += type; column += type; + packets = packets - 1; } } @@ -320,6 +352,7 @@ void DecodeLC(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data } // FUNCTION: LEGO1 0x100bdac0 +// FUNCTION: BETA10 0x1013e61d void DecodeSS2(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) { short width = (short) p_flcHeader->width - 1; @@ -384,40 +417,43 @@ void DecodeSS2(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_dat } // FUNCTION: LEGO1 0x100bdc00 +// FUNCTION: BETA10 0x1013e85a void DecodeBlack(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) { - short line = p_flcHeader->height; + short height = p_flcHeader->height; short width = p_flcHeader->width; + short t_col = 0; + short t_row = 0; BYTE pixel[2]; - pixel[1] = 0; - pixel[0] = 0; + pixel[0] = pixel[1] = 0; - while (--line >= 0) { - short count = width / 2; - short odd = width & 1; + for (short i = height - 1; i >= 0; i--) { + WritePixelPairs(p_bitmapHeader, p_pixelData, t_col, t_row + i, *(WORD*) pixel, width / 2); - WritePixelPairs(p_bitmapHeader, p_pixelData, 0, line, *((WORD*) pixel), count); - - if (odd) { - WritePixel(p_bitmapHeader, p_pixelData, width - 1, line, 0); + if (width & 1) { + WritePixel(p_bitmapHeader, p_pixelData, t_col + width - 1, t_row + i, 0); } } } // FUNCTION: LEGO1 0x100bdc90 +// FUNCTION: BETA10 0x1013e91f void DecodeCopy(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) { - short line = p_flcHeader->height; + short height = p_flcHeader->height; short width = p_flcHeader->width; + short t_col = 0; + short t_row = 0; - while (--line >= 0) { - WritePixels(p_bitmapHeader, p_pixelData, 0, line, p_data, width); + for (short i = height - 1; i >= 0; i--) { + WritePixels(p_bitmapHeader, p_pixelData, t_col, t_row + i, p_data, width); p_data += width; } } // FUNCTION: LEGO1 0x100bdce0 +// FUNCTION: BETA10 0x1013e9a5 void DecodeFLCFrame( LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, @@ -426,7 +462,12 @@ void DecodeFLCFrame( BYTE* p_decodedColorMap ) { - if (p_flcFrame->type == FLI_CHUNK_FRAME) { - DecodeChunks(p_bitmapHeader, p_pixelData, p_flcHeader, p_flcFrame, (BYTE*) (p_flcFrame + 1), p_decodedColorMap); + FLIC_FRAME* frame = p_flcFrame; + if (frame->type != FLI_CHUNK_FRAME) { + return; + } + + if (DecodeChunks(p_bitmapHeader, p_pixelData, p_flcHeader, frame, (BYTE*) (p_flcFrame + 1), p_decodedColorMap)) { + return; } } diff --git a/LEGO1/omni/src/video/mxflcpresenter.cpp b/LEGO1/omni/src/video/mxflcpresenter.cpp index ceacb85a..e618ea9e 100644 --- a/LEGO1/omni/src/video/mxflcpresenter.cpp +++ b/LEGO1/omni/src/video/mxflcpresenter.cpp @@ -44,6 +44,7 @@ void MxFlcPresenter::CreateBitmap() } // FUNCTION: LEGO1 0x100b3570 +// FUNCTION: BETA10 0x1013a10f void MxFlcPresenter::LoadFrame(MxStreamChunk* p_chunk) { MxU8* data = p_chunk->GetData();