Beta match progress for flic.cpp (#1162)

This commit is contained in:
MS 2024-11-21 19:07:40 -05:00 committed by GitHub
parent 5be9b343c4
commit 5e0dc1a160
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 140 additions and 97 deletions

View file

@ -7,6 +7,7 @@
#include <flic.h> #include <flic.h>
// VTABLE: LEGO1 0x100dc2c0 // VTABLE: LEGO1 0x100dc2c0
// VTABLE: BETA10 0x101c1eb0
// SIZE 0x68 // SIZE 0x68
class MxFlcPresenter : public MxVideoPresenter { class MxFlcPresenter : public MxVideoPresenter {
public: public:

View file

@ -40,7 +40,7 @@ short DecodeChunks(
); );
void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data); void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data);
void DecodeColorPackets(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 DecodeColors64(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data);
void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader); 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); 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); void DecodeCopy(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader);
// FUNCTION: LEGO1 0x100bd530 // FUNCTION: LEGO1 0x100bd530
// FUNCTION: BETA10 0x1013dd80
void WritePixel(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, short p_column, short p_row, byte p_pixel) 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) { 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; return;
} }
*(((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData) = p_pixel;
} }
// FUNCTION: LEGO1 0x100bd580 // FUNCTION: LEGO1 0x100bd580
// FUNCTION: BETA10 0x1013ddef
void WritePixels( void WritePixels(
LPBITMAPINFOHEADER p_bitmapHeader, LPBITMAPINFOHEADER p_bitmapHeader,
BYTE* p_pixelData, BYTE* p_pixelData,
@ -66,51 +70,55 @@ void WritePixels(
short p_count 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)) { if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) {
short offset = p_column - col; return;
BYTE* pixels = offset ? p_data + offset : p_data;
memcpy(((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData, pixels, p_count);
} }
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: LEGO1 0x100bd600
// FUNCTION: BETA10 0x1013de84
int ClampLine(LPBITMAPINFOHEADER p_bitmapHeader, short& p_column, short& p_row, short& p_count) int ClampLine(LPBITMAPINFOHEADER p_bitmapHeader, short& p_column, short& p_row, short& p_count)
{ {
short column = p_column; short column = p_column;
short row = p_row; short a_row = p_row;
short count = p_count; short f_count = p_count;
short end = column + count; short end = column + f_count;
int result;
if (row < 0 || p_bitmapHeader->biHeight <= row || end < 0 || p_bitmapHeader->biWidth <= column) { if (a_row < 0 || p_bitmapHeader->biHeight <= a_row || end < 0 || p_bitmapHeader->biWidth <= column) {
result = 0; return 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;
}
} }
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: LEGO1 0x100bd680
// FUNCTION: BETA10 0x1013df77
void WritePixelRun( void WritePixelRun(
LPBITMAPINFOHEADER p_bitmapHeader, LPBITMAPINFOHEADER p_bitmapHeader,
BYTE* p_pixelData, BYTE* p_pixelData,
@ -120,18 +128,19 @@ void WritePixelRun(
short p_count 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) { while (--p_count >= 0) {
*dst++ = p_pixel; *dst++ = p_pixel;
}
} }
} }
// FUNCTION: LEGO1 0x100bd6e0 // FUNCTION: LEGO1 0x100bd6e0
// FUNCTION: BETA10 0x1013dfee
void WritePixelPairs( void WritePixelPairs(
LPBITMAPINFOHEADER p_bitmapHeader, LPBITMAPINFOHEADER p_bitmapHeader,
BYTE* p_pixelData, BYTE* p_pixelData,
@ -143,22 +152,26 @@ void WritePixelPairs(
{ {
p_count <<= 1; p_count <<= 1;
if (ClampLine(p_bitmapHeader, p_column, p_row, p_count)) { if (!ClampLine(p_bitmapHeader, p_column, p_row, p_count)) {
short odd = p_count & 1; return;
p_count >>= 1; }
WORD* dst = (WORD*) (((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData); short is_odd = p_count & 1;
while (--p_count >= 0) { p_count >>= 1;
*dst++ = p_pixel;
}
if (odd) { WORD* dst = (WORD*) (((p_bitmapHeader->biWidth + 3) & -4) * p_row + p_column + p_pixelData);
*(BYTE*) dst = p_pixel; while (--p_count >= 0) {
} *dst++ = p_pixel;
}
if (is_odd) {
BYTE* dst_byte = (BYTE*) dst;
*dst_byte = p_pixel;
} }
} }
// FUNCTION: LEGO1 0x100bd760 // FUNCTION: LEGO1 0x100bd760
// FUNCTION: BETA10 0x1013e097
short DecodeChunks( short DecodeChunks(
LPBITMAPINFOHEADER p_bitmapHeader, LPBITMAPINFOHEADER p_bitmapHeader,
BYTE* p_pixelData, BYTE* p_pixelData,
@ -198,6 +211,8 @@ short DecodeChunks(
case FLI_CHUNK_COPY: case FLI_CHUNK_COPY:
DecodeCopy(p_bitmapHeader, p_pixelData, (BYTE*) (chunk + 1), p_flcHeader); DecodeCopy(p_bitmapHeader, p_pixelData, (BYTE*) (chunk + 1), p_flcHeader);
break; break;
default:
break;
} }
} }
@ -205,71 +220,81 @@ short DecodeChunks(
} }
// FUNCTION: LEGO1 0x100bd880 // FUNCTION: LEGO1 0x100bd880
// FUNCTION: BETA10 0x1013e22c
void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data) void DecodeColors256(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data)
{ {
DecodeColorPackets(p_bitmapHeader, p_data); DecodeColorPackets(p_bitmapHeader, p_data);
} }
// FUNCTION: LEGO1 0x100bd8a0 // FUNCTION: LEGO1 0x100bd8a0
// FUNCTION: BETA10 0x1013e24c
void DecodeColorPackets(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data) void DecodeColorPackets(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data)
{ {
WORD colorIndex = 0; short colorIndex = 0;
BYTE* colors = p_data + 2; BYTE* colors = p_data;
short* pPackets = (short*) colors;
short packets = *pPackets;
colors += 2;
for (short packet = *((short*) p_data) - 1; packet >= 0; packet--) { while (--packets >= 0) {
colorIndex += colors[0]; colorIndex += *colors++;
short colorCount = colors[1]; short colorCount = *colors++;
colors++; if (colorCount == 0) {
colors++;
if (!colorCount) {
colorCount = 256; colorCount = 256;
} }
DecodeColorPacket(p_bitmapHeader, colors, colorIndex, colorCount); DecodeColorPacket(p_bitmapHeader, colors, colorIndex, colorCount);
colorIndex += colorCount;
colors += colorCount * 3; colors += colorCount * 3;
colorIndex += colorCount;
} }
} }
// FUNCTION: LEGO1 0x100bd8f0 // 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) { while (p_count--) {
palette[2] = p_data[0]; palette->rgbRed = p_data[0];
palette[1] = p_data[1]; palette->rgbGreen = p_data[1];
palette[0] = p_data[2]; palette->rgbBlue = p_data[2];
palette += 4; palette++;
p_data += 3; p_data += 3;
} }
} }
// FUNCTION: LEGO1 0x100bd940 // FUNCTION: LEGO1 0x100bd940
// FUNCTION: BETA10 0x1013e364
void DecodeColors64(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data) void DecodeColors64(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_data)
{ {
DecodeColorPackets(p_bitmapHeader, p_data); DecodeColorPackets(p_bitmapHeader, p_data);
} }
// FUNCTION: LEGO1 0x100bd960 // FUNCTION: LEGO1 0x100bd960
// FUNCTION: BETA10 0x1013e384
void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) 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 width = p_flcHeader->width;
short height = p_flcHeader->height; short height = p_flcHeader->height;
BYTE* data = p_data;
BYTE* offset = ((p_bitmapHeader->biWidth + 3) & -4) * (height - 1) + p_pixelData; 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++; data++;
char count = 0;
while ((column += count) < width2) {
count = *data++;
for (short pixel = 0; pixel < width;) { short i;
char count = *data++;
if (count >= 0) { if (count >= 0) {
for (short i = 0; i < count; i++) { for (i = 0; i < count; i++) {
*offset++ = *data; *offset++ = *data;
} }
@ -277,12 +302,10 @@ void DecodeBrun(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_da
} }
else { else {
count = -count; count = -count;
for (short i = 0; i < count; i++) { for (i = 0; i < count; i++) {
*offset++ = *data++; *offset++ = *data++;
} }
} }
pixel += count;
} }
offset -= (((p_bitmapHeader->biWidth + 3) & -4) + width); 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: LEGO1 0x100bda10
// FUNCTION: BETA10 0x1013e4ca
void DecodeLC(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)
{ {
short row = (short) p_flcHeader->height - *((short*) p_data) - 1; short xofs = 0;
BYTE* data = p_data + 4; 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_data++;
WORD column = 0; short lines = *word_data;
while (--lines >= 0) {
short column = xofs;
BYTE packets = *data++; BYTE packets = *data++;
for (BYTE i = 0; i < packets; i++) { while (packets > 0) {
column += *data++; column += *data++; // skip byte
char type = *((char*) data++); char type = *((char*) data++);
if (type < 0) { if (type < 0) {
type = -type; type = -type;
WritePixelRun(p_bitmapHeader, p_pixelData, column, row, *data++, type); WritePixelRun(p_bitmapHeader, p_pixelData, column, row, *data++, type);
column += type; column += type;
packets = packets - 1;
} }
else { else {
WritePixels(p_bitmapHeader, p_pixelData, column, row, data, type); WritePixels(p_bitmapHeader, p_pixelData, column, row, data, type);
data += type; data += type;
column += 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: LEGO1 0x100bdac0
// FUNCTION: BETA10 0x1013e61d
void DecodeSS2(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) void DecodeSS2(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader)
{ {
short width = (short) p_flcHeader->width - 1; 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: LEGO1 0x100bdc00
// FUNCTION: BETA10 0x1013e85a
void DecodeBlack(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) 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 width = p_flcHeader->width;
short t_col = 0;
short t_row = 0;
BYTE pixel[2]; BYTE pixel[2];
pixel[1] = 0; pixel[0] = pixel[1] = 0;
pixel[0] = 0;
while (--line >= 0) { for (short i = height - 1; i >= 0; i--) {
short count = width / 2; WritePixelPairs(p_bitmapHeader, p_pixelData, t_col, t_row + i, *(WORD*) pixel, width / 2);
short odd = width & 1;
WritePixelPairs(p_bitmapHeader, p_pixelData, 0, line, *((WORD*) pixel), count); if (width & 1) {
WritePixel(p_bitmapHeader, p_pixelData, t_col + width - 1, t_row + i, 0);
if (odd) {
WritePixel(p_bitmapHeader, p_pixelData, width - 1, line, 0);
} }
} }
} }
// FUNCTION: LEGO1 0x100bdc90 // FUNCTION: LEGO1 0x100bdc90
// FUNCTION: BETA10 0x1013e91f
void DecodeCopy(LPBITMAPINFOHEADER p_bitmapHeader, BYTE* p_pixelData, BYTE* p_data, FLIC_HEADER* p_flcHeader) 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 width = p_flcHeader->width;
short t_col = 0;
short t_row = 0;
while (--line >= 0) { for (short i = height - 1; i >= 0; i--) {
WritePixels(p_bitmapHeader, p_pixelData, 0, line, p_data, width); WritePixels(p_bitmapHeader, p_pixelData, t_col, t_row + i, p_data, width);
p_data += width; p_data += width;
} }
} }
// FUNCTION: LEGO1 0x100bdce0 // FUNCTION: LEGO1 0x100bdce0
// FUNCTION: BETA10 0x1013e9a5
void DecodeFLCFrame( void DecodeFLCFrame(
LPBITMAPINFOHEADER p_bitmapHeader, LPBITMAPINFOHEADER p_bitmapHeader,
BYTE* p_pixelData, BYTE* p_pixelData,
@ -426,7 +462,12 @@ void DecodeFLCFrame(
BYTE* p_decodedColorMap BYTE* p_decodedColorMap
) )
{ {
if (p_flcFrame->type == FLI_CHUNK_FRAME) { FLIC_FRAME* frame = p_flcFrame;
DecodeChunks(p_bitmapHeader, p_pixelData, p_flcHeader, p_flcFrame, (BYTE*) (p_flcFrame + 1), p_decodedColorMap); if (frame->type != FLI_CHUNK_FRAME) {
return;
}
if (DecodeChunks(p_bitmapHeader, p_pixelData, p_flcHeader, frame, (BYTE*) (p_flcFrame + 1), p_decodedColorMap)) {
return;
} }
} }

View file

@ -44,6 +44,7 @@ void MxFlcPresenter::CreateBitmap()
} }
// FUNCTION: LEGO1 0x100b3570 // FUNCTION: LEGO1 0x100b3570
// FUNCTION: BETA10 0x1013a10f
void MxFlcPresenter::LoadFrame(MxStreamChunk* p_chunk) void MxFlcPresenter::LoadFrame(MxStreamChunk* p_chunk)
{ {
MxU8* data = p_chunk->GetData(); MxU8* data = p_chunk->GetData();