From 3674ad20615c04f343936053b71de039cdc8e3d6 Mon Sep 17 00:00:00 2001 From: yoshizf Date: Sun, 21 Sep 2003 23:50:28 +0000 Subject: [PATCH] Added basic SMUSH frame viewer/dumper --- Makefile | 2 +- bomp.cpp | 388 +++++++++++++++++++++++++++++++ bomp.h | 36 +++ codec37.cpp | 513 +++++++++++++++++++++++++++++++++++++++++ codec37.h | 56 +++++ codec47.cpp | 628 ++++++++++++++++++++++++++++++++++++++++++++++++++ codec47.h | 60 +++++ image.cpp | 56 ++++- image.h | 8 +- resource.h | 6 +- scummex.cpp | 9 +- scummex.h | 3 +- wxwindows.cpp | 9 +- 13 files changed, 1765 insertions(+), 9 deletions(-) create mode 100644 bomp.cpp create mode 100644 bomp.h create mode 100644 codec37.cpp create mode 100644 codec37.h create mode 100644 codec47.cpp create mode 100644 codec47.h diff --git a/Makefile b/Makefile index 623dd4f..710d796 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ CP := cp RESSW := --define __WIN32__ --define __WIN95__ --define __GNUWIN32__ REZ_CMD := `wx-config --rezflags` -OBJS := file.o scummex.o resource.o mixer.o image.o sound.o wxwindows.o descumm.o descumm6.o +OBJS := file.o scummex.o resource.o mixer.o image.o sound.o wxwindows.o descumm.o descumm6.o codec37.o codec47.o bomp.o CXXFLAGS := -DOSUNIX -g -O -Wall -Wuninitialized -Wshadow -Wstrict-prototypes -Wno-unused-variable -Wno-long-long -Wno-multichar -Wno-unknown-pragmas CXXFLAGS += `wx-config --cxxflags` `sdl-config --cflags` LIBS := `wx-config --libs` `sdl-config --libs` -lSDL_mixer diff --git a/bomp.cpp b/bomp.cpp new file mode 100644 index 0000000..afda562 --- /dev/null +++ b/bomp.cpp @@ -0,0 +1,388 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001 Ludvig Strigeus + * Copyright (C) 2001-2003 The ScummVM 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/bomp.cpp,v 1.1 2003/09/21 23:50:28 yoshizf Exp $ + * + */ + +#include "stdafx.h" +#include "bomp.h" + +byte defaultScaleTable[768]; +byte revBitMask[8]; + +static void bompScaleFuncX(byte *line_buffer, byte *scaling_x_ptr, byte skip, int32 size); + +static void bompApplyShadow0(const byte *line_buffer, byte *dst, int32 size, byte transparency); +static void bompApplyShadow1(const byte *shadowPalette, const byte *line_buffer, byte *dst, int32 size, byte transparency); +static void bompApplyShadow3(const byte *shadowPalette, const byte *line_buffer, byte *dst, int32 size, byte transparency); +static void bompApplyActorPalette(byte *actorPalette, byte *line_buffer, int32 size); + + + +void decompressBomp(byte *dst, const byte *src, int w, int h) { + assert(w > 0); + assert(h > 0); + + do { + bompDecodeLine(dst, src + 2, w); + src += READ_LE_UINT16(src) + 2; + dst += w; + } while (--h); +} + +void bompDecodeLine(byte *dst, const byte *src, int size) { + assert(size > 0); + + int len, num; + byte code, color; + + len = size; + while (len) { + code = *src++; + num = (code >> 1) + 1; + if (num > len) + num = len; + len -= num; + if (code & 1) { + color = *src++; + memset(dst, color, num); + } else { + memcpy(dst, src, num); + src += num; + } + dst += num; + } +} + +void bompDecodeLineReverse(byte *dst, const byte *src, int size) { + assert(size > 0); + + dst += size; + + int len, num; + byte code, color; + + len = size; + while (len) { + code = *src++; + num = (code >> 1) + 1; + if (num > len) + num = len; + len -= num; + dst -= num; + if (code & 1) { + color = *src++; + memset(dst, color, num); + } else { + memcpy(dst, src, num); + src += num; + } + } +} + +void bompApplyMask(byte *line_buffer, byte *mask, byte maskbit, int32 size, byte transparency) { + while (1) { + do { + if (size-- == 0) + return; + if (*mask & maskbit) { + *line_buffer = transparency; + } + line_buffer++; + maskbit >>= 1; + } while (maskbit); + mask++; + maskbit = 128; + } +} + +void bompApplyShadow(int shadowMode, const byte *shadowPalette, const byte *line_buffer, byte *dst, int32 size, byte transparency) { + assert(size > 0); + switch(shadowMode) { + case 0: + bompApplyShadow0(line_buffer, dst, size, transparency); + break; + case 1: + bompApplyShadow1(shadowPalette, line_buffer, dst, size, transparency); + break; + case 3: + bompApplyShadow3(shadowPalette, line_buffer, dst, size, transparency); + break; + default: + printf("Unknown shadow mode %d", shadowMode); + } +} +void bompApplyShadow0(const byte *line_buffer, byte *dst, int32 size, byte transparency) { + while (size-- > 0) { + byte tmp = *line_buffer++; + if (tmp != transparency) { + *dst = tmp; + } + dst++; + } +} + +void bompApplyShadow1(const byte *shadowPalette, const byte *line_buffer, byte *dst, int32 size, byte transparency) { + while (size-- > 0) { + byte tmp = *line_buffer++; + if (tmp != transparency) { + if (tmp == 13) { + tmp = shadowPalette[*dst]; + } + *dst = tmp; + } + dst++; + } +} + +void bompApplyShadow3(const byte *shadowPalette, const byte *line_buffer, byte *dst, int32 size, byte transparency) { + while (size-- > 0) { + byte tmp = *line_buffer++; + if (tmp != transparency) { + if (tmp < 8) { + tmp = shadowPalette[*dst + (tmp << 8)]; + } + *dst = tmp; + } + dst++; + } +} + +void bompApplyActorPalette(byte *actorPalette, byte *line_buffer, int32 size) { + if (actorPalette != 0) { + actorPalette[255] = 255; + while (size-- > 0) { + *line_buffer = actorPalette[*line_buffer]; + line_buffer++; + } + } +} + +void bompScaleFuncX(byte *line_buffer, byte *scaling_x_ptr, byte skip, int32 size) { + byte *line_ptr1 = line_buffer; + byte *line_ptr2 = line_buffer; + + byte tmp = *scaling_x_ptr++; + + while (size--) { + if ((skip & tmp) == 0) { + *line_ptr1++ = *line_ptr2; + } + line_ptr2++; + skip >>= 1; + if (skip == 0) { + skip = 128; + tmp = *scaling_x_ptr++; + } + } +} + +/*void Scumm::drawBomp(const BompDrawData &bd, bool mirror) { + const byte *src; + byte *dst; + byte maskbit; + byte *mask = 0; + byte *charset_mask; + int clip_left, clip_right, clip_top, clip_bottom; + byte *scalingYPtr = bd.scalingYPtr; + byte skip_y_bits = 0x80; + byte skip_y_new = 0; + byte tmp; + + + if (bd.x < 0) { + clip_left = -bd.x; + } else { + clip_left = 0; + } + + if (bd.y < 0) { + clip_top = -bd.y; + } else { + clip_top = 0; + } + + clip_right = bd.srcwidth; + if (clip_right > bd.outwidth - bd.x) { + clip_right = bd.outwidth - bd.x; + } + + clip_bottom = bd.srcheight; + if (clip_bottom > bd.outheight - bd.y) { + clip_bottom = bd.outheight - bd.y; + } + + src = bd.dataptr; + dst = bd.out + bd.y * bd.outwidth + bd.x + clip_left; + + maskbit = revBitMask[(bd.x + clip_left) & 7]; + + // Always mask against the charset mask + charset_mask = getMaskBuffer(bd.x + clip_left, bd.y, 0); + + // Also mask against any additionally imposed mask + if (bd.maskPtr) { + mask = bd.maskPtr + (bd.y * gdi._numStrips) + ((bd.x + clip_left) >> 3); + } + + // Setup vertical scaling + if (bd.scale_y != 255) { + assert(scalingYPtr); + + skip_y_new = *scalingYPtr++; + skip_y_bits = 0x80; + + if (clip_bottom > bd.scaleBottom) { + clip_bottom = bd.scaleBottom; + } + } + + // Setup horizontal scaling + if (bd.scale_x != 255) { + assert(bd.scalingXPtr); + if (clip_right > bd.scaleRight) { + clip_right = bd.scaleRight; + } + } + + const int width = clip_right - clip_left; + + if (width <= 0) + return; + + int pos_y = 0; + byte line_buffer[1024]; + + byte *line_ptr = line_buffer + clip_left; + + // Loop over all lines + while (pos_y < clip_bottom) { + // Decode a single (bomp encoded) line, reversed if we are in mirror mode + if (mirror) + bompDecodeLineReverse(line_buffer, src + 2, bd.srcwidth); + else + bompDecodeLine(line_buffer, src + 2, bd.srcwidth); + src += READ_LE_UINT16(src) + 2; + + // If vertical scaling is enabled, do it + if (bd.scale_y != 255) { + // A bit set means we should skip this line... + tmp = skip_y_new & skip_y_bits; + + // Advance the scale-skip bit mask, if it's 0, get the next scale-skip byte + skip_y_bits >>= 1; + if (skip_y_bits == 0) { + skip_y_bits = 0x80; + skip_y_new = *scalingYPtr++; + } + + // Skip the current line if the above check tells us to + if (tmp != 0) + continue; + } + + // Perform horizontal scaling + if (bd.scale_x != 255) { + bompScaleFuncX(line_buffer, bd.scalingXPtr, 0x80, bd.srcwidth); + } + + // The first clip_top lines are to be clipped, i.e. not drawn + if (clip_top > 0) { + clip_top--; + } else { + // Replace the parts of the line which are masked with the transparency color + if (bd.maskPtr) + bompApplyMask(line_ptr, mask, maskbit, width, 255); + bompApplyMask(line_ptr, charset_mask, maskbit, width, 255); + + // Apply custom color map, if available + if (_bompActorPalettePtr) + bompApplyActorPalette(_bompActorPalettePtr, line_ptr, width); + + // Finally, draw the decoded, scaled, masked and recolored line onto + // the target surface, using the specified shadow mode + bompApplyShadow(bd.shadowMode, _shadowPalette, line_ptr, dst, width, 255); + } + + // Advance to the next line + pos_y++; + mask += gdi._numStrips; + charset_mask += gdi._numStrips; + dst += bd.outwidth; + } +}*/ + +static const byte bitCount[] = { + 8, 7, 7, 6, 7, 6, 6, 5, 7, 6, 6, 5, 6, 5, 5, 4, + 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, + 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, + 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, + 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, + 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, + 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, + 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, + 7, 6, 6, 5, 6, 5, 5, 4, 6, 5, 5, 4, 5, 4, 4, 3, + 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, + 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, + 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, + 6, 5, 5, 4, 5, 4, 4, 3, 5, 4, 4, 3, 4, 3, 3, 2, + 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, + 5, 4, 4, 3, 4, 3, 3, 2, 4, 3, 3, 2, 3, 2, 2, 1, + 4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0, +}; + +int32 setupBompScale(byte *scaling, int32 size, byte scale) { + byte tmp; + int32 count; + const byte *tmp_ptr; + byte *tmp_scaling = scaling; + byte a = 0; + byte ret_value = 0; + const int offsets[8] = { 3, 2, 1, 0, 7, 6, 5, 4 }; + + count = (256 - (size >> 1)); + assert(0 <= count && count < 768); + tmp_ptr = defaultScaleTable + count; + + count = (size + 7) >> 3; + while (count--) { + a = 0; + for (int i = 0; i < 8; i++) { + tmp = *(tmp_ptr + offsets[i]); + a <<= 1; + if (scale < tmp) { + a |= 1; + } + } + tmp_ptr += 8; + + *tmp_scaling++ = a; + } + if ((size & 7) != 0) { + *(tmp_scaling - 1) |= revBitMask[size & 7]; + } + + count = (size + 7) >> 3; + while (count--) { + tmp = *scaling++; + ret_value += bitCount[tmp]; + } + + return ret_value; +} + diff --git a/bomp.h b/bomp.h new file mode 100644 index 0000000..51477e2 --- /dev/null +++ b/bomp.h @@ -0,0 +1,36 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001 Ludvig Strigeus + * Copyright (C) 2001-2003 The ScummVM 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/bomp.h,v 1.1 2003/09/21 23:50:28 yoshizf Exp $ + * + */ + +#ifndef BOMP_H +#define BOMP_H + +#include "scummsys.h" + +int32 setupBompScale(byte *scaling, int32 size, byte scale); + +void bompApplyMask(byte *line_buffer, byte *mask, byte maskbit, int32 size, byte transparency); +void bompApplyShadow(int shadowMode, const byte *shadowPalette, const byte *line_buffer, byte *dst, int32 size, byte transparency); + +void decompressBomp(byte *dst, const byte *src, int w, int h); +void bompDecodeLine(byte *dst, const byte *src, int size); +void bompDecodeLineReverse(byte *dst, const byte *src, int size); + +#endif diff --git a/codec37.cpp b/codec37.cpp new file mode 100644 index 0000000..4c2714a --- /dev/null +++ b/codec37.cpp @@ -0,0 +1,513 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002-2003 The ScummVM 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/codec37.cpp,v 1.1 2003/09/21 23:50:28 yoshizf Exp $ + * + */ + +#include "stdafx.h" +#include "bomp.h" +#include "codec37.h" + +void Codec37Decoder::init(int width, int height) { + deinit(); + _width = width; + _height = height; + _frameSize = _width * _height; + _deltaSize = _frameSize * 3 + 0x13600; + _deltaBuf = (byte *)calloc(_deltaSize, sizeof(byte)); + if (_deltaBuf == 0) + printf("unable to allocate decoder buffer"); + _deltaBufs[0] = _deltaBuf + 0x4D80; + _deltaBufs[1] = _deltaBuf + 0xE880 + _frameSize; + _offsetTable = new int16[255]; + _curtable = 0; + if (_offsetTable == 0) + printf("unable to allocate decoder offset table"); + _tableLastPitch = -1; + _tableLastIndex = -1; +} + +Codec37Decoder::Codec37Decoder() { + _deltaSize = 0; + _deltaBuf = 0; + _deltaBufs[0] = 0; + _deltaBufs[1] = 0; + _curtable = 0; + _offsetTable = 0; + _tableLastPitch = -1; + _tableLastIndex = -1; + _prevSeqNb = 0; +} + +void Codec37Decoder::deinit() { + if (_offsetTable) { + delete []_offsetTable; + _offsetTable = 0; + _tableLastPitch = -1; + _tableLastIndex = -1; + } + if (_deltaBuf) { + free(_deltaBuf); + _deltaSize = 0; + _deltaBuf = 0; + _deltaBufs[0] = 0; + _deltaBufs[1] = 0; + } +} + +Codec37Decoder::~Codec37Decoder() { + deinit(); +} + +void Codec37Decoder::maketable(int pitch, int index) { + static const int8 maketable_bytes[] = { + 0, 0, 1, 0, 2, 0, 3, 0, 5, 0, + 8, 0, 13, 0, 21, 0, -1, 0, -2, 0, + -3, 0, -5, 0, -8, 0, -13, 0, -17, 0, + -21, 0, 0, 1, 1, 1, 2, 1, 3, 1, + 5, 1, 8, 1, 13, 1, 21, 1, -1, 1, + -2, 1, -3, 1, -5, 1, -8, 1, -13, 1, + -17, 1, -21, 1, 0, 2, 1, 2, 2, 2, + 3, 2, 5, 2, 8, 2, 13, 2, 21, 2, + -1, 2, -2, 2, -3, 2, -5, 2, -8, 2, + -13, 2, -17, 2, -21, 2, 0, 3, 1, 3, + 2, 3, 3, 3, 5, 3, 8, 3, 13, 3, + 21, 3, -1, 3, -2, 3, -3, 3, -5, 3, + -8, 3, -13, 3, -17, 3, -21, 3, 0, 5, + 1, 5, 2, 5, 3, 5, 5, 5, 8, 5, + 13, 5, 21, 5, -1, 5, -2, 5, -3, 5, + -5, 5, -8, 5, -13, 5, -17, 5, -21, 5, + 0, 8, 1, 8, 2, 8, 3, 8, 5, 8, + 8, 8, 13, 8, 21, 8, -1, 8, -2, 8, + -3, 8, -5, 8, -8, 8, -13, 8, -17, 8, + -21, 8, 0, 13, 1, 13, 2, 13, 3, 13, + 5, 13, 8, 13, 13, 13, 21, 13, -1, 13, + -2, 13, -3, 13, -5, 13, -8, 13, -13, 13, + -17, 13, -21, 13, 0, 21, 1, 21, 2, 21, + 3, 21, 5, 21, 8, 21, 13, 21, 21, 21, + -1, 21, -2, 21, -3, 21, -5, 21, -8, 21, + -13, 21, -17, 21, -21, 21, 0, -1, 1, -1, + 2, -1, 3, -1, 5, -1, 8, -1, 13, -1, + 21, -1, -1, -1, -2, -1, -3, -1, -5, -1, + -8, -1, -13, -1, -17, -1, -21, -1, 0, -2, + 1, -2, 2, -2, 3, -2, 5, -2, 8, -2, + 13, -2, 21, -2, -1, -2, -2, -2, -3, -2, + -5, -2, -8, -2, -13, -2, -17, -2, -21, -2, + 0, -3, 1, -3, 2, -3, 3, -3, 5, -3, + 8, -3, 13, -3, 21, -3, -1, -3, -2, -3, + -3, -3, -5, -3, -8, -3, -13, -3, -17, -3, + -21, -3, 0, -5, 1, -5, 2, -5, 3, -5, + 5, -5, 8, -5, 13, -5, 21, -5, -1, -5, + -2, -5, -3, -5, -5, -5, -8, -5, -13, -5, + -17, -5, -21, -5, 0, -8, 1, -8, 2, -8, + 3, -8, 5, -8, 8, -8, 13, -8, 21, -8, + -1, -8, -2, -8, -3, -8, -5, -8, -8, -8, + -13, -8, -17, -8, -21, -8, 0, -13, 1, -13, + 2, -13, 3, -13, 5, -13, 8, -13, 13, -13, + 21, -13, -1, -13, -2, -13, -3, -13, -5, -13, + -8, -13, -13, -13, -17, -13, -21, -13, 0, -17, + 1, -17, 2, -17, 3, -17, 5, -17, 8, -17, + 13, -17, 21, -17, -1, -17, -2, -17, -3, -17, + -5, -17, -8, -17, -13, -17, -17, -17, -21, -17, + 0, -21, 1, -21, 2, -21, 3, -21, 5, -21, + 8, -21, 13, -21, 21, -21, -1, -21, -2, -21, + -3, -21, -5, -21, -8, -21, -13, -21, -17, -21, + 0, 0, -8, -29, 8, -29, -18, -25, 17, -25, + 0, -23, -6, -22, 6, -22, -13, -19, 12, -19, + 0, -18, 25, -18, -25, -17, -5, -17, 5, -17, + -10, -15, 10, -15, 0, -14, -4, -13, 4, -13, + 19, -13, -19, -12, -8, -11, -2, -11, 0, -11, + 2, -11, 8, -11, -15, -10, -4, -10, 4, -10, + 15, -10, -6, -9, -1, -9, 1, -9, 6, -9, + -29, -8, -11, -8, -8, -8, -3, -8, 3, -8, + 8, -8, 11, -8, 29, -8, -5, -7, -2, -7, + 0, -7, 2, -7, 5, -7, -22, -6, -9, -6, + -6, -6, -3, -6, -1, -6, 1, -6, 3, -6, + 6, -6, 9, -6, 22, -6, -17, -5, -7, -5, + -4, -5, -2, -5, 0, -5, 2, -5, 4, -5, + 7, -5, 17, -5, -13, -4, -10, -4, -5, -4, + -3, -4, -1, -4, 0, -4, 1, -4, 3, -4, + 5, -4, 10, -4, 13, -4, -8, -3, -6, -3, + -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, + 1, -3, 2, -3, 4, -3, 6, -3, 8, -3, + -11, -2, -7, -2, -5, -2, -3, -2, -2, -2, + -1, -2, 0, -2, 1, -2, 2, -2, 3, -2, + 5, -2, 7, -2, 11, -2, -9, -1, -6, -1, + -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, + 1, -1, 2, -1, 3, -1, 4, -1, 6, -1, + 9, -1, -31, 0, -23, 0, -18, 0, -14, 0, + -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, + -2, 0, -1, 0, 0, -31, 1, 0, 2, 0, + 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, + 14, 0, 18, 0, 23, 0, 31, 0, -9, 1, + -6, 1, -4, 1, -3, 1, -2, 1, -1, 1, + 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, + 6, 1, 9, 1, -11, 2, -7, 2, -5, 2, + -3, 2, -2, 2, -1, 2, 0, 2, 1, 2, + 2, 2, 3, 2, 5, 2, 7, 2, 11, 2, + -8, 3, -6, 3, -4, 3, -2, 3, -1, 3, + 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, + 6, 3, 8, 3, -13, 4, -10, 4, -5, 4, + -3, 4, -1, 4, 0, 4, 1, 4, 3, 4, + 5, 4, 10, 4, 13, 4, -17, 5, -7, 5, + -4, 5, -2, 5, 0, 5, 2, 5, 4, 5, + 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, + -3, 6, -1, 6, 1, 6, 3, 6, 6, 6, + 9, 6, 22, 6, -5, 7, -2, 7, 0, 7, + 2, 7, 5, 7, -29, 8, -11, 8, -8, 8, + -3, 8, 3, 8, 8, 8, 11, 8, 29, 8, + -6, 9, -1, 9, 1, 9, 6, 9, -15, 10, + -4, 10, 4, 10, 15, 10, -8, 11, -2, 11, + 0, 11, 2, 11, 8, 11, 19, 12, -19, 13, + -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, + -5, 17, 5, 17, 25, 17, -25, 18, 0, 18, + -12, 19, 13, 19, -6, 22, 6, 22, 0, 23, + -17, 25, 18, 25, -8, 29, 8, 29, 0, 31, + 0, 0, -6, -22, 6, -22, -13, -19, 12, -19, + 0, -18, -5, -17, 5, -17, -10, -15, 10, -15, + 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, + -8, -11, -2, -11, 0, -11, 2, -11, 8, -11, + -15, -10, -4, -10, 4, -10, 15, -10, -6, -9, + -1, -9, 1, -9, 6, -9, -11, -8, -8, -8, + -3, -8, 0, -8, 3, -8, 8, -8, 11, -8, + -5, -7, -2, -7, 0, -7, 2, -7, 5, -7, + -22, -6, -9, -6, -6, -6, -3, -6, -1, -6, + 1, -6, 3, -6, 6, -6, 9, -6, 22, -6, + -17, -5, -7, -5, -4, -5, -2, -5, -1, -5, + 0, -5, 1, -5, 2, -5, 4, -5, 7, -5, + 17, -5, -13, -4, -10, -4, -5, -4, -3, -4, + -2, -4, -1, -4, 0, -4, 1, -4, 2, -4, + 3, -4, 5, -4, 10, -4, 13, -4, -8, -3, + -6, -3, -4, -3, -3, -3, -2, -3, -1, -3, + 0, -3, 1, -3, 2, -3, 3, -3, 4, -3, + 6, -3, 8, -3, -11, -2, -7, -2, -5, -2, + -4, -2, -3, -2, -2, -2, -1, -2, 0, -2, + 1, -2, 2, -2, 3, -2, 4, -2, 5, -2, + 7, -2, 11, -2, -9, -1, -6, -1, -5, -1, + -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, + 1, -1, 2, -1, 3, -1, 4, -1, 5, -1, + 6, -1, 9, -1, -23, 0, -18, 0, -14, 0, + -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, + -2, 0, -1, 0, 0, -23, 1, 0, 2, 0, + 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, + 14, 0, 18, 0, 23, 0, -9, 1, -6, 1, + -5, 1, -4, 1, -3, 1, -2, 1, -1, 1, + 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, + 5, 1, 6, 1, 9, 1, -11, 2, -7, 2, + -5, 2, -4, 2, -3, 2, -2, 2, -1, 2, + 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, + 5, 2, 7, 2, 11, 2, -8, 3, -6, 3, + -4, 3, -3, 3, -2, 3, -1, 3, 0, 3, + 1, 3, 2, 3, 3, 3, 4, 3, 6, 3, + 8, 3, -13, 4, -10, 4, -5, 4, -3, 4, + -2, 4, -1, 4, 0, 4, 1, 4, 2, 4, + 3, 4, 5, 4, 10, 4, 13, 4, -17, 5, + -7, 5, -4, 5, -2, 5, -1, 5, 0, 5, + 1, 5, 2, 5, 4, 5, 7, 5, 17, 5, + -22, 6, -9, 6, -6, 6, -3, 6, -1, 6, + 1, 6, 3, 6, 6, 6, 9, 6, 22, 6, + -5, 7, -2, 7, 0, 7, 2, 7, 5, 7, + -11, 8, -8, 8, -3, 8, 0, 8, 3, 8, + 8, 8, 11, 8, -6, 9, -1, 9, 1, 9, + 6, 9, -15, 10, -4, 10, 4, 10, 15, 10, + -8, 11, -2, 11, 0, 11, 2, 11, 8, 11, + 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, + -10, 15, 10, 15, -5, 17, 5, 17, 0, 18, + -12, 19, 13, 19, -6, 22, 6, 22, 0, 23, + }; + + if (_tableLastPitch == pitch && _tableLastIndex == index) + return; + + _tableLastPitch = pitch; + _tableLastIndex = index; + index *= 255; + assert(index + 254 < (int32)(sizeof(maketable_bytes) / 2)); + + for (int32 i = 0; i < 255; i++) { + int32 j = (i + index) << 1; + _offsetTable[i] = maketable_bytes[j + 1] * pitch + maketable_bytes[j]; + } +} + +#if defined(SCUMM_NEED_ALIGNMENT) + +#define DECLARE_LITERAL_TEMP(v) \ + byte v + +#define READ_LITERAL_PIXEL(src, v) \ + v = *src++ + +#define WRITE_4X1_LINE(dst, v) \ + do { \ + int j; \ + for (j=0; j<4; j++) \ + (dst)[j] = v; \ + } while (0) + +#define COPY_4X1_LINE(dst, src) \ + do { \ + int j; \ + for (j=0; j<4; j++) \ + (dst)[j] = (src)[j]; \ + } while (0) + +#else /* SCUMM_NEED_ALIGNMENT */ + +#define DECLARE_LITERAL_TEMP(v) \ + uint32 v + +#define READ_LITERAL_PIXEL(src, v) \ + do { \ + v = *src++; \ + v += (v << 8) + (v << 16) + (v << 24); \ + } while (0) + +#define WRITE_4X1_LINE(dst, v) \ + *(uint32 *)(dst) = v + +#define COPY_4X1_LINE(dst, src) \ + *(uint32 *)(dst) = *(const uint32 *)(src) + +#endif /* SCUMM_NEED_ALIGNMENT */ + +/* Fill a 4x4 pixel block with a literal pixel value */ + +#define LITERAL_4X4(src, dst, pitch) \ + do { \ + int x; \ + DECLARE_LITERAL_TEMP(t); \ + READ_LITERAL_PIXEL(src, t); \ + for (x=0; x<4; x++) { \ + WRITE_4X1_LINE(dst + pitch * x, t); \ + } \ + dst += 4; \ + } while (0) + +/* Fill four 4x1 pixel blocks with literal pixel values */ + +#define LITERAL_4X1(src, dst, pitch) \ + do { \ + int x; \ + DECLARE_LITERAL_TEMP(t); \ + for (x=0; x<4; x++) { \ + READ_LITERAL_PIXEL(src, t); \ + WRITE_4X1_LINE(dst + pitch * x, t); \ + } \ + dst += 4; \ + } while (0) + +/* Fill sixteen 1x1 pixel blocks with literal pixel values */ + +#define LITERAL_1X1(src, dst, pitch) \ + do { \ + int x; \ + for (x=0; x<4; x++) { \ + COPY_4X1_LINE(dst + pitch * x, src); \ + src += 4; \ + } \ + dst += 4; \ + } while (0) + +/* Copy a 4x4 pixel block from a different place in the framebuffer */ + +#define COPY_4X4(dst2, dst, pitch) \ + do { \ + int x; \ + for (x=0; x<4; x++) { \ + COPY_4X1_LINE(dst + pitch * x, dst2 + pitch * x); \ + } \ + dst += 4; \ + } while (0) + +void Codec37Decoder::proc3WithFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) { + do { + int32 i = bw; + do { + int32 code = *src++; + if (code == 0xFD) { + LITERAL_4X4(src, dst, pitch); + } else if (code == 0xFE) { + LITERAL_4X1(src, dst, pitch); + } else if (code == 0xFF) { + LITERAL_1X1(src, dst, pitch); + } else { + byte *dst2 = dst + _offsetTable[code] + next_offs; + COPY_4X4(dst2, dst, pitch); + } + } while (--i); + dst += pitch * 3; + } while (--bh); +} + +void Codec37Decoder::proc3WithoutFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) { + do { + int32 i = bw; + do { + int32 code = *src++; + if (code == 0xFF) { + LITERAL_1X1(src, dst, pitch); + } else { + byte *dst2 = dst + _offsetTable[code] + next_offs; + COPY_4X4(dst2, dst, pitch); + } + } while (--i); + dst += pitch * 3; + } while (--bh); +} + +void Codec37Decoder::proc4WithFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) { + do { + int32 i = bw; + do { + int32 code = *src++; + if (code == 0xFD) { + LITERAL_4X4(src, dst, pitch); + } else if (code == 0xFE) { + LITERAL_4X1(src, dst, pitch); + } else if (code == 0xFF) { + LITERAL_1X1(src, dst, pitch); + } else if (code == 0x00) { + int32 length = *src++ + 1; + for (int32 l = 0; l < length; l++) { + byte *dst2 = dst + next_offs; + COPY_4X4(dst2, dst, pitch); + i--; + if (i == 0) { + dst += pitch * 3; + bh--; + i = bw; + } + } + if (bh == 0) { + return; + } + i++; + } else { + byte *dst2 = dst + _offsetTable[code] + next_offs; + COPY_4X4(dst2, dst, pitch); + } + } while (--i); + dst += pitch * 3; + } while (--bh); +} + +void Codec37Decoder::proc4WithoutFDFE(byte *dst, const byte *src, int32 next_offs, int bw, int bh, int pitch, int16 *offset_table) { + do { + int32 i = bw; + do { + int32 code = *src++; + if (code == 0xFF) { + LITERAL_1X1(src, dst, pitch); + } else if (code == 0x00) { + int32 length = *src++ + 1; + for (int32 l = 0; l < length; l++) { + byte *dst2 = dst + next_offs; + COPY_4X4(dst2, dst, pitch); + i--; + if (i == 0) { + dst += pitch * 3; + bh--; + i = bw; + } + } + if (bh == 0) { + return; + } + i++; + } else { + byte *dst2 = dst + _offsetTable[code] + next_offs; + COPY_4X4(dst2, dst, pitch); + } + } while (--i); + dst += pitch * 3; + } while (--bh); +} + +void Codec37Decoder::decode(byte *dst, const byte *src) { + int32 bw = (_width + 3) >> 2, bh = (_height + 3) >> 2; + int32 pitch = bw << 2; + + int16 seq_nb = READ_LE_UINT16(src + 2); + int32 decoded_size = READ_LE_UINT32(src + 4); + byte mask_flags = src[12]; + maketable(pitch, src[1]); + int32 tmp; + + switch(src[0]) { + case 0: + if ((_deltaBufs[_curtable] - _deltaBuf) > 0) { + memset(_deltaBuf, 0, _deltaBufs[_curtable] - _deltaBuf); + } + tmp = (_deltaBuf + _deltaSize) - _deltaBufs[_curtable] - decoded_size; + if (tmp > 0) { + memset(_deltaBufs[_curtable] + decoded_size, 0, tmp); + } + memcpy(_deltaBufs[_curtable], src + 16, decoded_size); + break; + case 1: + printf("codec37: missing opcode 1"); + break; + case 2: + bompDecodeLine(_deltaBufs[_curtable], src + 16, decoded_size); + if ((_deltaBufs[_curtable] - _deltaBuf) > 0) { + memset(_deltaBuf, 0, _deltaBufs[_curtable] - _deltaBuf); + } + tmp = (_deltaBuf + _deltaSize) - _deltaBufs[_curtable] - decoded_size; + if (tmp > 0) { + memset(_deltaBufs[_curtable] + decoded_size, 0, tmp); + } + break; + case 3: + if ((seq_nb & 1) || !(mask_flags & 1)) { + _curtable ^= 1; + } + + if ((mask_flags & 4) != 0) { + proc3WithFDFE(_deltaBufs[_curtable], src + 16, + _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh, + pitch, _offsetTable); + } else { + proc3WithoutFDFE(_deltaBufs[_curtable], src + 16, + _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh, + pitch, _offsetTable); + } + break; + case 4: + if ((seq_nb & 1) || !(mask_flags & 1)) { + _curtable ^= 1; + } + + if ((mask_flags & 4) != 0) { + proc4WithFDFE(_deltaBufs[_curtable], src + 16, + _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh, + pitch, _offsetTable); + } else { + proc4WithoutFDFE(_deltaBufs[_curtable], src + 16, + _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh, + pitch, _offsetTable); + } + break; + default: + break; + } + _prevSeqNb = seq_nb; + + memcpy(dst, _deltaBufs[_curtable], _frameSize); +} + diff --git a/codec37.h b/codec37.h new file mode 100644 index 0000000..aefce51 --- /dev/null +++ b/codec37.h @@ -0,0 +1,56 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002-2003 The ScummVM 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/codec37.h,v 1.1 2003/09/21 23:50:28 yoshizf Exp $ + * + */ + +#ifndef SMUSH_CODEC37_H +#define SMUSH_CODEC37_H + +#include "scummsys.h" + +class Codec37Decoder { +private: + + int32 _deltaSize; + byte *_deltaBufs[2]; + byte *_deltaBuf; + int16 *_offsetTable; + int _curtable; + uint16 _prevSeqNb; + int _tableLastPitch; + int _tableLastIndex; + int32 _frameSize; + int _width, _height; + +public: + Codec37Decoder(); + ~Codec37Decoder(); + void init(int width, int height); + void deinit(); +protected: + void maketable(int, int); + void proc3WithFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *); + void proc3WithoutFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *); + void proc4WithFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *); + void proc4WithoutFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *); +public: + void decode(byte *dst, const byte *src); +}; + +#endif diff --git a/codec47.cpp b/codec47.cpp new file mode 100644 index 0000000..8986fe3 --- /dev/null +++ b/codec47.cpp @@ -0,0 +1,628 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002-2003 The ScummVM 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/codec47.cpp,v 1.1 2003/09/21 23:50:28 yoshizf Exp $ + * + */ + +#include "stdafx.h" +#include "bomp.h" +#include "codec47.h" + +#if defined(SCUMM_NEED_ALIGNMENT) + +#define COPY_4X1_LINE(dst, src) \ + do { \ + (dst)[0] = (src)[0]; \ + (dst)[1] = (src)[1]; \ + (dst)[2] = (src)[2]; \ + (dst)[3] = (src)[3]; \ + } while (0) + +#define COPY_2X1_LINE(dst, src) \ + do { \ + (dst)[0] = (src)[0]; \ + (dst)[1] = (src)[1]; \ + } while (0) + + +#else /* SCUMM_NEED_ALIGNMENT */ + +#define COPY_4X1_LINE(dst, src) \ + *(uint32 *)(dst) = *(const uint32 *)(src) + +#define COPY_2X1_LINE(dst, src) \ + *(uint16 *)(dst) = *(const uint16 *)(src) + +#endif + +#define FILL_4X1_LINE(dst, val) \ + do { \ + (dst)[0] = val; \ + (dst)[1] = val; \ + (dst)[2] = val; \ + (dst)[3] = val; \ + } while (0) + +#define FILL_2X1_LINE(dst, val) \ + do { \ + (dst)[0] = val; \ + (dst)[1] = val; \ + } while (0) + +static int8 codec47_table_small1[] = { + 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1, +}; + +static int8 codec47_table_small2[] = { + 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2, +}; + +static int8 codec47_table_big1[] = { + 0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0, +}; + +static int8 codec47_table_big2[] = { + 0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1, +}; + +#ifdef __PALM_OS__ +static int8 *codec47_table; +#else +static int8 codec47_table[] = { + 0, 0, -1, -43, 6, -43, -9, -42, 13, -41, + -16, -40, 19, -39, -23, -36, 26, -34, -2, -33, + 4, -33, -29, -32, -9, -32, 11, -31, -16, -29, + 32, -29, 18, -28, -34, -26, -22, -25, -1, -25, + 3, -25, -7, -24, 8, -24, 24, -23, 36, -23, + -12, -22, 13, -21, -38, -20, 0, -20, -27, -19, + -4, -19, 4, -19, -17, -18, -8, -17, 8, -17, + 18, -17, 28, -17, 39, -17, -12, -15, 12, -15, + -21, -14, -1, -14, 1, -14, -41, -13, -5, -13, + 5, -13, 21, -13, -31, -12, -15, -11, -8, -11, + 8, -11, 15, -11, -2, -10, 1, -10, 31, -10, + -23, -9, -11, -9, -5, -9, 4, -9, 11, -9, + 42, -9, 6, -8, 24, -8, -18, -7, -7, -7, + -3, -7, -1, -7, 2, -7, 18, -7, -43, -6, + -13, -6, -4, -6, 4, -6, 8, -6, -33, -5, + -9, -5, -2, -5, 0, -5, 2, -5, 5, -5, + 13, -5, -25, -4, -6, -4, -3, -4, 3, -4, + 9, -4, -19, -3, -7, -3, -4, -3, -2, -3, + -1, -3, 0, -3, 1, -3, 2, -3, 4, -3, + 6, -3, 33, -3, -14, -2, -10, -2, -5, -2, + -3, -2, -2, -2, -1, -2, 0, -2, 1, -2, + 2, -2, 3, -2, 5, -2, 7, -2, 14, -2, + 19, -2, 25, -2, 43, -2, -7, -1, -3, -1, + -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, + 3, -1, 10, -1, -5, 0, -3, 0, -2, 0, + -1, 0, 1, 0, 2, 0, 3, 0, 5, 0, + 7, 0, -10, 1, -7, 1, -3, 1, -2, 1, + -1, 1, 0, 1, 1, 1, 2, 1, 3, 1, + -43, 2, -25, 2, -19, 2, -14, 2, -5, 2, + -3, 2, -2, 2, -1, 2, 0, 2, 1, 2, + 2, 2, 3, 2, 5, 2, 7, 2, 10, 2, + 14, 2, -33, 3, -6, 3, -4, 3, -2, 3, + -1, 3, 0, 3, 1, 3, 2, 3, 4, 3, + 19, 3, -9, 4, -3, 4, 3, 4, 7, 4, + 25, 4, -13, 5, -5, 5, -2, 5, 0, 5, + 2, 5, 5, 5, 9, 5, 33, 5, -8, 6, + -4, 6, 4, 6, 13, 6, 43, 6, -18, 7, + -2, 7, 0, 7, 2, 7, 7, 7, 18, 7, + -24, 8, -6, 8, -42, 9, -11, 9, -4, 9, + 5, 9, 11, 9, 23, 9, -31, 10, -1, 10, + 2, 10, -15, 11, -8, 11, 8, 11, 15, 11, + 31, 12, -21, 13, -5, 13, 5, 13, 41, 13, + -1, 14, 1, 14, 21, 14, -12, 15, 12, 15, + -39, 17, -28, 17, -18, 17, -8, 17, 8, 17, + 17, 18, -4, 19, 0, 19, 4, 19, 27, 19, + 38, 20, -13, 21, 12, 22, -36, 23, -24, 23, + -8, 24, 7, 24, -3, 25, 1, 25, 22, 25, + 34, 26, -18, 28, -32, 29, 16, 29, -11, 31, + 9, 32, 29, 32, -4, 33, 2, 33, -26, 34, + 23, 36, -19, 39, 16, 40, -13, 41, 9, 42, + -6, 43, 1, 43, 0, 0, 0, 0, 0, 0 +}; +#endif + +void Codec47Decoder::makeTablesInterpolation(int param) { + int32 variable1, variable2; + int32 b1, b2; + int32 value_table47_1_2, value_table47_1_1, value_table47_2_2, value_table47_2_1; + int32 tableSmallBig[64], tmp, s; + int8 *table47_1 = 0, *table47_2 = 0; + int32 *ptr_small_big; + byte *ptr; + int i, x, y; + + if (param == 8) { + table47_1 = codec47_table_big1; + table47_2 = codec47_table_big2; + ptr = _tableBig + 384; + for (i = 0; i < 256; i++) { + *ptr = 0; + ptr += 388; + } + ptr = _tableBig + 385; + for (i = 0; i < 256; i++) { + *ptr = 0; + ptr += 388; + } + } else if (param == 4) { + table47_1 = codec47_table_small1; + table47_2 = codec47_table_small2; + ptr = _tableSmall + 96; + for (i = 0; i < 256; i++) { + *ptr = 0; + ptr += 128; + } + ptr = _tableSmall + 97; + for (i = 0; i < 256; i++) { + *ptr = 0; + ptr += 128; + } + } else { + printf("Codec47Decoder::makeTablesInterpolation: unknown param %d", param); + } + + s = 0; + for (x = 0; x < 16; x++) { + value_table47_1_1 = table47_1[x]; + value_table47_2_1 = table47_2[x]; + for (y = 0; y < 16; y++) { + value_table47_1_2 = table47_1[y]; + value_table47_2_2 = table47_2[y]; + + if (value_table47_2_1 == 0) { + b1 = 0; + } else if (value_table47_2_1 == param - 1) { + b1 = 1; + } else if (value_table47_1_1 == 0) { + b1 = 2; + } else if (value_table47_1_1 == param - 1) { + b1 = 3; + } else { + b1 = 4; + } + + if (value_table47_2_2 == 0) { + b2 = 0; + } else if (value_table47_2_2 == param - 1) { + b2 = 1; + } else if (value_table47_1_2 == 0) { + b2 = 2; + } else if (value_table47_1_2 == param - 1) { + b2 = 3; + } else { + b2 = 4; + } + + memset(tableSmallBig, 0, param * param * 4); + + variable2 = abs(value_table47_2_2 - value_table47_2_1); + tmp = abs(value_table47_1_2 - value_table47_1_1); + if (variable2 <= tmp) { + variable2 = tmp; + } + + for (variable1 = 0; variable1 <= variable2; variable1++) { + int32 variable3, variable4; + + if (variable2 > 0) { + // Linearly interpolate between value_table47_1_1 and value_table47_1_2 + // respectively value_table47_2_1 and value_table47_2_2. + variable4 = (value_table47_1_1 * variable1 + value_table47_1_2 * (variable2 - variable1) + variable2 / 2) / variable2; + variable3 = (value_table47_2_1 * variable1 + value_table47_2_2 * (variable2 - variable1) + variable2 / 2) / variable2; + } else { + variable4 = value_table47_1_1; + variable3 = value_table47_2_1; + } + ptr_small_big = &tableSmallBig[param * variable3 + variable4]; + *ptr_small_big = 1; + + if ((b1 == 2 && b2 == 3) || (b2 == 2 && b1 == 3) || + (b1 == 0 && b2 != 1) || (b2 == 0 && b1 != 1)) { + if (variable3 >= 0) { + i = variable3 + 1; + while (i--) { + *ptr_small_big = 1; + ptr_small_big -= param; + } + } + } else if ((b2 != 0 && b1 == 1) || (b1 != 0 && b2 == 1)) { + if (param > variable3) { + i = param - variable3; + while (i--) { + *ptr_small_big = 1; + ptr_small_big += param; + } + } + } else if ((b1 == 2 && b2 != 3) || (b2 == 2 && b1 != 3)) { + if (variable4 >= 0) { + i = variable4 + 1; + while (i--) { + *(ptr_small_big--) = 1; + } + } + } else if ((b1 == 0 && b2 == 1) || (b2 == 0 && b1 == 1) || + (b1 == 3 && b2 != 2) || (b2 == 3 && b1 != 2)) { + if (param > variable4) { + i = param - variable4; + while (i--) { + *(ptr_small_big++) = 1; + } + } + } + } + + if (param == 8) { + for (i = 64 - 1; i >= 0; i--) { + if (tableSmallBig[i] != 0) { + _tableBig[256 + s + _tableBig[384 + s]] = (byte)i; + _tableBig[384 + s]++; + } else { + _tableBig[320 + s + _tableBig[385 + s]] = (byte)i; + _tableBig[385 + s]++; + } + } + s += 388; + } + if (param == 4) { + for (i = 16 - 1; i >= 0; i--) { + if (tableSmallBig[i] != 0) { + _tableSmall[64 + s + _tableSmall[96 + s]] = (byte)i; + _tableSmall[96 + s]++; + } else { + _tableSmall[80 + s + _tableSmall[97 + s]] = (byte)i; + _tableSmall[97 + s]++; + } + } + s += 128; + } + } + } +} + +void Codec47Decoder::makeTables47(int width) { + if (_lastTableWidth == width) + return; + + _lastTableWidth = width; + + int32 a, c, d; + int16 tmp; + + for (int l = 0; l < 512; l += 2) { + _table[l >> 1] = (int16)(codec47_table[l + 1] * width + codec47_table[l]); + } + + a = 0; + c = 0; + do { + for (d = 0; d < _tableSmall[96 + c]; d++) { + tmp = _tableSmall[64 + c + d]; + tmp = (int16)((byte)(tmp >> 2) * width + (tmp & 3)); + _tableSmall[c + d * 2] = (byte)tmp; + _tableSmall[c + d * 2 + 1] = tmp >> 8; + } + for (d = 0; d < _tableSmall[97 + c]; d++) { + tmp = _tableSmall[80 + c + d]; + tmp = (int16)((byte)(tmp >> 2) * width + (tmp & 3)); + _tableSmall[32 + c + d * 2] = (byte)tmp; + _tableSmall[32 + c + d * 2 + 1] = tmp >> 8; + } + for (d = 0; d < _tableBig[384 + a]; d++) { + tmp = _tableBig[256 + a + d]; + tmp = (int16)((byte)(tmp >> 3) * width + (tmp & 7)); + _tableBig[a + d * 2] = (byte)tmp; + _tableBig[a + d * 2 + 1] = tmp >> 8; + } + for (d = 0; d < _tableBig[385 + a]; d++) { + tmp = _tableBig[320 + a + d]; + tmp = (int16)((byte)(tmp >> 3) * width + (tmp & 7)); + _tableBig[128 + a + d * 2] = (byte)tmp; + _tableBig[128 + a + d * 2 + 1] = tmp >> 8; + } + + a += 388; + c += 128; + } while (c < 32768); +} + +void Codec47Decoder::level3(byte *d_dst) { + int32 tmp; + byte code = *_d_src++; + + if (code < 0xF8) { + tmp = _table[code] + _offset1; + COPY_2X1_LINE(d_dst, d_dst + tmp); + COPY_2X1_LINE(d_dst + _d_pitch, d_dst + _d_pitch + tmp); + } else if (code == 0xFF) { + COPY_2X1_LINE(d_dst, _d_src + 0); + COPY_2X1_LINE(d_dst + _d_pitch, _d_src + 2); + _d_src += 4; + } else if (code == 0xFE) { + byte t = *_d_src++; + FILL_2X1_LINE(d_dst, t); + FILL_2X1_LINE(d_dst + _d_pitch, t); + } else if (code == 0xFC) { + tmp = _offset2; + COPY_2X1_LINE(d_dst, d_dst + tmp); + COPY_2X1_LINE(d_dst + _d_pitch, d_dst + _d_pitch + tmp); + } else { + byte t = _paramPtr[code]; + FILL_2X1_LINE(d_dst, t); + FILL_2X1_LINE(d_dst + _d_pitch, t); + } +} + +void Codec47Decoder::level2(byte *d_dst) { + int32 tmp; + byte code = *_d_src++; + int i; + + if (code < 0xF8) { + tmp = _table[code] + _offset1; + for (i = 0; i < 4; i++) { + COPY_4X1_LINE(d_dst, d_dst + tmp); + d_dst += _d_pitch; + } + } else if (code == 0xFF) { + byte *tmp_dst = d_dst; + level3(d_dst); + d_dst += 2; + level3(d_dst); + d_dst += _d_pitch * 2 - 2; + level3(d_dst); + d_dst += 2; + level3(d_dst); + d_dst = tmp_dst; + } else if (code == 0xFE) { + byte t = *_d_src++; + for (i = 0; i < 4; i++) { + FILL_4X1_LINE(d_dst, t); + d_dst += _d_pitch; + } + } else if (code == 0xFD) { + byte *tmp_ptr = _tableSmall + (*_d_src++ << 7); + int32 l = tmp_ptr[96]; + byte val = *_d_src++; + int16 *tmp_ptr2 = (int16 *)tmp_ptr; + while (l--) { + *(d_dst + READ_LE_UINT16(tmp_ptr2)) = val; + tmp_ptr2++; + } + l = tmp_ptr[97]; + val = *_d_src++; + tmp_ptr2 = (int16 *)(tmp_ptr + 32); + while (l--) { + *(d_dst + READ_LE_UINT16(tmp_ptr2)) = val; + tmp_ptr2++; + } + } else if (code == 0xFC) { + tmp = _offset2; + for (i = 0; i < 4; i++) { + COPY_4X1_LINE(d_dst, d_dst + tmp); + d_dst += _d_pitch; + } + } else { + byte t = _paramPtr[code]; + for (i = 0; i < 4; i++) { + FILL_4X1_LINE(d_dst, t); + d_dst += _d_pitch; + } + } +} + +void Codec47Decoder::level1(byte *d_dst) { + int32 tmp, tmp2; + byte code = *_d_src++; + int i; + + if (code < 0xF8) { + tmp2 = _table[code] + _offset1; + for (i = 0; i < 8; i++) { + COPY_4X1_LINE(d_dst + 0, d_dst + tmp2); + COPY_4X1_LINE(d_dst + 4, d_dst + tmp2 + 4); + d_dst += _d_pitch; + } + } else if (code == 0xFF) { + byte *tmp_dst = d_dst; + level2(d_dst); + d_dst += 4; + level2(d_dst); + d_dst += _d_pitch * 4 - 4; + level2(d_dst); + d_dst += 4; + level2(d_dst); + d_dst = tmp_dst; + } else if (code == 0xFE) { + byte t = *_d_src++; + for (i = 0; i < 8; i++) { + FILL_4X1_LINE(d_dst, t); + FILL_4X1_LINE(d_dst + 4, t); + d_dst += _d_pitch; + } + } else if (code == 0xFD) { + tmp = *_d_src++; + byte *tmp_ptr = _tableBig + (tmp << 2) + (tmp << 7) + (tmp << 8); + byte l = tmp_ptr[384]; + byte val = *_d_src++; + int16 *tmp_ptr2 = (int16 *)tmp_ptr; + while (l--) { + *(d_dst + READ_LE_UINT16(tmp_ptr2)) = val; + tmp_ptr2++; + } + l = tmp_ptr[385]; + val = *_d_src++; + tmp_ptr2 = (int16 *)(tmp_ptr + 128); + while (l--) { + *(d_dst + READ_LE_UINT16(tmp_ptr2)) = val; + tmp_ptr2++; + } + } else if (code == 0xFC) { + tmp2 = _offset2; + for (i = 0; i < 8; i++) { + COPY_4X1_LINE(d_dst + 0, d_dst + tmp2); + COPY_4X1_LINE(d_dst + 4, d_dst + tmp2 + 4); + d_dst += _d_pitch; + } + } else { + byte t = _paramPtr[code]; + for (i = 0; i < 8; i++) { + FILL_4X1_LINE(d_dst, t); + FILL_4X1_LINE(d_dst + 4, t); + d_dst += _d_pitch; + } + } +} + +void Codec47Decoder::decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr) { + _d_src = src; + _paramPtr = param_ptr - 0xf8; + int bw = (width + 7) >> 3; + int bh = (height + 7) >> 3; + int next_line = width * 7; + _d_pitch = width; + + do { + int tmp_bw = bw; + do { + level1(dst); + dst += 8; + } while (--tmp_bw); + dst += next_line; + } while (--bh); +} + +void Codec47Decoder::init(int width, int height) { + deinit(); + _width = width; + _height = height; + makeTablesInterpolation(4); + makeTablesInterpolation(8); + + _frameSize = _width * _height; + _deltaSize = _frameSize * 3; + _deltaBuf = (byte *)malloc(_deltaSize); + _deltaBufs[0] = _deltaBuf; + _deltaBufs[1] = _deltaBuf + _frameSize; + _curBuf = _deltaBuf + _frameSize * 2; +} + +Codec47Decoder::Codec47Decoder() { + _tableBig = (byte *)malloc(99328); + _tableSmall = (byte *)malloc(32768); + _deltaBuf = 0; +} + +void Codec47Decoder::deinit() { + _lastTableWidth = -1; + if (_deltaBuf) { + free(_deltaBuf); + _deltaSize = 0; + _deltaBuf = 0; + _deltaBufs[0] = 0; + _deltaBufs[1] = 0; + } + if (_tableBig == NULL) { + free(_tableBig); + _tableBig = NULL; + } + if (_tableSmall == NULL) { + free(_tableSmall); + _tableSmall = NULL; + } +} + +Codec47Decoder::~Codec47Decoder() { + deinit(); +} + +bool Codec47Decoder::decode(byte *dst, const byte *src) { + _offset1 = _deltaBufs[1] - _curBuf; + _offset2 = _deltaBufs[0] - _curBuf; + + int32 seq_nb = READ_LE_UINT16(src + 0); + + const byte *gfx_data = src + 26; + byte *tmp_ptr; + + if (seq_nb == 0) { + makeTables47(_width); + memset(_deltaBufs[0], src[12], _frameSize); + memset(_deltaBufs[1], src[13], _frameSize); + _prevSeqNb = -1; + } + + if ((src[4] & 1) != 0) { + gfx_data += 32896; + } + + switch(src[2]) { + case 0: + memcpy(_curBuf, gfx_data, _frameSize); + break; + case 1: + printf("codec47: not implemented decode1 proc"); + break; + case 2: + if (seq_nb == _prevSeqNb + 1) { + decode2(_curBuf, gfx_data, _width, _height, src + 8); + } + break; + case 3: + memcpy(_curBuf, _deltaBufs[1], _frameSize); + break; + case 4: + memcpy(_curBuf, _deltaBufs[0], _frameSize); + break; + case 5: + bompDecodeLine(_curBuf, gfx_data, READ_LE_UINT32(src + 14)); + break; + } + + memcpy(dst, _curBuf, _frameSize); + + if (seq_nb == _prevSeqNb + 1) { + if (src[3] == 1) { + tmp_ptr = _curBuf; + _curBuf = _deltaBufs[1]; + _deltaBufs[1] = tmp_ptr; + } else if (src[3] == 2) { + tmp_ptr = _deltaBufs[0]; + _deltaBufs[0] = _deltaBufs[1]; + _deltaBufs[1] = _curBuf; + _curBuf = tmp_ptr; + } + } + _prevSeqNb = seq_nb; + + return true; +} + +#ifdef __PALM_OS__ +#include "scumm_globals.h" + +_GINIT(Codec47) +_GSETPTR(codec47_table, GBVARS_CODEC47TABLE_INDEX, int8, GBVARS_SCUMM) +_GEND + +_GRELEASE(Codec47) +_GRELEASEPTR(GBVARS_CODEC47TABLE_INDEX, GBVARS_SCUMM) +_GEND + +#endif diff --git a/codec47.h b/codec47.h new file mode 100644 index 0000000..248f633 --- /dev/null +++ b/codec47.h @@ -0,0 +1,60 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2002-2003 The ScummVM 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 2 + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/codec47.h,v 1.1 2003/09/21 23:50:28 yoshizf Exp $ + * + */ + +#ifndef SMUSH_CODEC_47_H +#define SMUSH_CODEC_47_H + +#include "scummsys.h" + +class Codec47Decoder { +private: + + int32 _deltaSize; + byte *_deltaBufs[2]; + byte *_deltaBuf; + byte *_curBuf; + int32 _prevSeqNb; + int _lastTableWidth; + const byte *_d_src, *_paramPtr; + int _d_pitch; + int32 _offset1, _offset2; + byte *_tableBig; + byte *_tableSmall; + int16 _table[256]; + int32 _frameSize; + int _width, _height; + + void makeTablesInterpolation(int param); + void makeTables47(int width); + void level1(byte *d_dst); + void level2(byte *d_dst); + void level3(byte *d_dst); + void decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr); + +public: + Codec47Decoder(); + ~Codec47Decoder(); + void init(int width, int height); + void deinit(); + bool decode(byte *dst, const byte *src); +}; + +#endif diff --git a/image.cpp b/image.cpp index d28ae91..f109ec2 100644 --- a/image.cpp +++ b/image.cpp @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * $Header: /Users/sev/projects/sc/s/scummvm/scummex/image.cpp,v 1.5 2003/09/21 18:33:04 yoshizf Exp $ + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/image.cpp,v 1.6 2003/09/21 23:50:28 yoshizf Exp $ * */ @@ -74,6 +74,60 @@ int Image::drawPalette(BlockTable *_blockTable, int id, File& _input) return 0; } +int Image::drawSmushFrame(BlockTable *_blockTable, int id, File& _input) { + int index; + int x = 0, y = 0; + byte *dst, *dstorg, *chunk_buffer; + + index = _resource->findBlock(0, _blockTable, _input, id, "NPAL", "AHDR", "-1"); + if (_blockTable[index].blockTypeID == AHDR) { + _input.seek(_blockTable[index].offset + 14, SEEK_SET); + } else { + _input.seek(_blockTable[index].offset + 8, SEEK_SET); + } + + for (int j = 0; j < 256; j++) { + _rgbTable[j].red = _input.readByte(); // red + _rgbTable[j].green = _input.readByte(); // green + _rgbTable[j].blue = _input.readByte(); // blue + } + + _input.seek(_blockTable[id].offset + 22, SEEK_SET); + _codec37.init(_blockTable[id].width, _blockTable[id].height); + _codec47.init(_blockTable[id].width, _blockTable[id].height); + chunk_buffer = (byte *)malloc(_blockTable[id].blockSize - 22); + dstorg = dst = (byte *)malloc(_blockTable[id].width*_blockTable[id].height); + _input.read(chunk_buffer, _blockTable[id].blockSize - 22); + + switch (_blockTable[id].variables) { + case 1: + bompDecodeLine(dst, chunk_buffer, _blockTable[id].blockSize - 22); + break; + + case 37: + _codec37.decode(dst, chunk_buffer); + break; + + case 47: + _codec47.decode(dst, chunk_buffer); + break; + } + + _gui->DisplayImage("SMUSH Frame", _blockTable[id].width, _blockTable[id].height); + + for (y=0; y<_blockTable[id].height; y++) { + for (x=0; x<_blockTable[id].width; x++) { + int color = *dst++; + _gui->PutPixel(x, y, _rgbTable[color].red, _rgbTable[color].green, _rgbTable[color].blue); + } + } + + free(chunk_buffer); + free(dstorg); + _gui->DrawImage(); + return 0; +} + int Image::drawBG(File& _input, BlockTable *_blockTable, int id, char* filename) { int RMHDindex, CLUTindex, SMAPindex, TRNSindex; diff --git a/image.h b/image.h index 85c42af..ada78af 100644 --- a/image.h +++ b/image.h @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * $Header: /Users/sev/projects/sc/s/scummvm/scummex/image.h,v 1.4 2003/09/19 15:47:42 fingolfin Exp $ + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/image.h,v 1.5 2003/09/21 23:50:28 yoshizf Exp $ * */ @@ -24,6 +24,9 @@ #define image_h #include "scummsys.h" +#include "codec37.h" +#include "codec47.h" +#include "bomp.h" struct rgbtable { int red; @@ -41,6 +44,8 @@ private: int _height; Resource *_resource; GUI_wxWindows *_gui; + Codec37Decoder _codec37; + Codec47Decoder _codec47; public: Image(); @@ -48,6 +53,7 @@ public: int drawPalette(BlockTable *_blockTable, int id, File& _input); int drawBG(File& _input, BlockTable *_blockTable, int id, char* filename); int drawObject(File& _input, BlockTable *_blockTable, int id); + int drawSmushFrame(BlockTable *_blockTable, int id, File& _input); void decode_uncompressed(uint16 height, File& _input); void decode_horiz(uint16 height, uint8 compr, File& _input); void decode_vert(uint16 height, uint8 compr, File& _input); diff --git a/resource.h b/resource.h index 32a7e8d..401f346 100644 --- a/resource.h +++ b/resource.h @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * $Header: /Users/sev/projects/sc/s/scummvm/scummex/resource.h,v 1.5 2003/09/21 18:33:04 yoshizf Exp $ + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/resource.h,v 1.6 2003/09/21 23:50:28 yoshizf Exp $ * */ @@ -41,9 +41,9 @@ struct BlockTable { uint32 arrays; uint32 characters; uint32 invObjects; - uint32 width; + int32 width; int trans; - uint32 height; + int32 height; }; struct RoomTable { diff --git a/scummex.cpp b/scummex.cpp index a34dc88..5c45106 100644 --- a/scummex.cpp +++ b/scummex.cpp @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * $Header: /Users/sev/projects/sc/s/scummvm/scummex/scummex.cpp,v 1.12 2003/09/21 18:42:21 yoshizf Exp $ + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/scummex.cpp,v 1.13 2003/09/21 23:50:28 yoshizf Exp $ * */ @@ -273,6 +273,12 @@ void ScummEX::bgDraw() _image->drawBG(_input, _blockTable, _blockId, ""); } +void ScummEX::SmushFrameDraw() +{ + _image = new Image(); + _image->drawSmushFrame(_blockTable, _blockId, _input); +} + void ScummEX::objectDraw() { _image = new Image(); @@ -383,6 +389,7 @@ void ScummEX::UpdateInfosFromTree(int blockid) { _gui->updateLabel("SpecLabel1", "Frame Width", _blockTable[blockid].width); _gui->updateLabel("SpecLabel2", "Frame Height", _blockTable[blockid].height); _gui->updateLabel("SpecLabel3", "Codec", _blockTable[blockid].variables); + _gui->SetButton(_blockTable[blockid].blockTypeID); break; } } diff --git a/scummex.h b/scummex.h index 6a349e1..ed07ae8 100644 --- a/scummex.h +++ b/scummex.h @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * $Header: /Users/sev/projects/sc/s/scummvm/scummex/scummex.h,v 1.5 2003/09/19 19:57:07 yoshizf Exp $ + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/scummex.h,v 1.6 2003/09/21 23:50:28 yoshizf Exp $ * */ @@ -61,6 +61,7 @@ public: void SOUPlay(); void paletteDraw(); void bgDraw(); + void SmushFrameDraw(); void objectDraw(); }; diff --git a/wxwindows.cpp b/wxwindows.cpp index 4311bad..50b733b 100644 --- a/wxwindows.cpp +++ b/wxwindows.cpp @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - * $Header: /Users/sev/projects/sc/s/scummvm/scummex/wxwindows.cpp,v 1.10 2003/09/21 18:42:21 yoshizf Exp $ + * $Header: /Users/sev/projects/sc/s/scummvm/scummex/wxwindows.cpp,v 1.11 2003/09/21 23:50:28 yoshizf Exp $ * */ @@ -369,6 +369,13 @@ void GUI_wxWindows::SetButton(int blocktype) { (wxObjectEventFunction) &ScummEX::bgDraw ); break; + case FOBJ: + SpecButton1->SetLabel("View Frame"); + SpecButton1->Show(TRUE); + SpecButton1->Connect( ID_SpecButton1, wxEVT_COMMAND_BUTTON_CLICKED, + (wxObjectEventFunction) &ScummEX::SmushFrameDraw ); + break; + case LSCR: case SCRP: case ENCD: