diff options
author | Max Horn | 2006-02-11 22:45:04 +0000 |
---|---|---|
committer | Max Horn | 2006-02-11 22:45:04 +0000 |
commit | 26ee630756ebdd7c96bccede0881a8c8b98e8f2b (patch) | |
tree | 26e378d5cf990a2b81c2c96e9e683a7f333b62e8 /engines/lure/decode.cpp | |
parent | 2a9a0d4211b1ea5723f1409d91cb95de8984429e (diff) | |
download | scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.tar.gz scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.tar.bz2 scummvm-rg350-26ee630756ebdd7c96bccede0881a8c8b98e8f2b.zip |
Moved engines to the new engines/ directory
svn-id: r20582
Diffstat (limited to 'engines/lure/decode.cpp')
-rw-r--r-- | engines/lure/decode.cpp | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/engines/lure/decode.cpp b/engines/lure/decode.cpp new file mode 100644 index 0000000000..c04e4dca5b --- /dev/null +++ b/engines/lure/decode.cpp @@ -0,0 +1,360 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2005-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "lure/decode.h" +#include "lure/memory.h" +#include "lure/luredefs.h" + +namespace Lure { + +/*--------------------------------------------------------------------------*/ +/* PictureDecoder class */ +/* */ +/* Provides the functionality for decoding screens */ +/*--------------------------------------------------------------------------*/ + +void PictureDecoder::writeByte(MemoryBlock *dest, byte v) { + if (outputOffset == dest->size()) + error("Decoded data exceeded allocated output buffer size"); + dest->data()[outputOffset++] = v; +} + +void PictureDecoder::writeBytes(MemoryBlock *dest, byte v, uint16 numBytes) { + if (outputOffset + numBytes > dest->size()) + error("Decoded data exceeded allocated output buffer size"); + dest->memorySet(v, outputOffset, numBytes); + outputOffset += numBytes; +} + +byte PictureDecoder::DSSI(bool incr) { + byte result = dataIn[dataPos]; + if (incr) ++dataPos; + return result; +} + +byte PictureDecoder::ESBX(bool incr) { + byte result = dataIn[dataPos2]; + if (incr) ++dataPos2; + return result; +} + +void PictureDecoder::decrCtr() { + --CL; + if (CL == 0) { + CH = ESBX(); + CL = 8; + } +} + +bool PictureDecoder::shlCarry() { + bool result = (CH & 0x80) != 0; + CH <<= 1; + return result; +} + +void PictureDecoder::swap(uint16 &v1, uint16 &v2) { + uint16 vTemp; + vTemp = v1; + v1 = v2; + v2 = vTemp; +} + +// decode_data +// Takes care of decoding compressed Lure of the Temptress data + +MemoryBlock *PictureDecoder::decode(MemoryBlock *src, uint32 maxOutputSize) { + MemoryBlock *dest = Memory::allocate(maxOutputSize); + + // Set up initial states + dataIn = src->data(); + outputOffset = 0; + dataPos = READ_LE_UINT32(dataIn + 0x400); + dataPos2 = 0x404; + + CH = ESBX(); + CL = 9; + +Loc754: + AL = DSSI(); + writeByte(dest, AL); + BP = ((uint16) AL) << 2; + +Loc755: + decrCtr(); + if (shlCarry()) goto Loc761; + decrCtr(); + if (shlCarry()) goto Loc759; + AL = dataIn[BP]; + +Loc758: + writeByte(dest, AL); + BP = ((uint16) AL) << 2; + goto Loc755; + +Loc759: + AL = (byte) (BP >> 2); + AH = DSSI(); + if (AH == 0) goto Loc768; + + writeBytes(dest, AL, AH); + goto Loc755; + +Loc761: + decrCtr(); + if (shlCarry()) goto Loc765; + decrCtr(); + + if (shlCarry()) goto Loc764; + AL = dataIn[BP+1]; + goto Loc758; + +Loc764: + AL = dataIn[BP+2]; + goto Loc758; + +Loc765: + decrCtr(); + if (shlCarry()) goto Loc767; + AL = dataIn[BP+3]; + goto Loc758; + +Loc767: + goto Loc754; + +Loc768: + AL = DSSI(); + if (AL != 0) goto Loc755; + + // Resize the output to be the number of outputed bytes and return it + if (outputOffset < dest->size()) dest->reallocate(outputOffset); + return dest; +} + +/*--------------------------------------------------------------------------*/ +/* AnimationDecoder class */ +/* */ +/* Provides the functionality for decoding animations */ +/*--------------------------------------------------------------------------*/ + +// The code below is responsible for decompressing the pixel data +// for an animation. I'm not currently sure of the of the exact details +// of the compression format - for now I've simply copied the code +// from the executable + +void AnimationDecoder::rcl(uint16 &value, bool &carry) { + bool result = (value & 0x8000) != 0; + value = (value << 1) + (carry ? 1 : 0); + carry = result; +} + +#define GET_BYTE currData = (currData & 0xff00) | *pSrc++ +#define BX_VAL(x) *((byte *) (dest->data() + tableOffset + x)) +#define SET_HI_BYTE(x,v) x = (x & 0xff) | ((v) << 8); +#define SET_LO_BYTE(x,v) x = (x & 0xff00) | (v); + +void AnimationDecoder::decode_data_2(byte *&pSrc, uint16 &currData, uint16 &bitCtr, + uint16 &dx, bool &carry) { + SET_HI_BYTE(dx, currData >> 8); + + for (int v = 0; v < 8; ++v) { + rcl(currData, carry); + if (--bitCtr == 0) { + GET_BYTE; + bitCtr = 8; + } + } +} + +uint32 AnimationDecoder::decode_data(MemoryBlock *src, MemoryBlock *dest, uint32 srcPos) { + byte *pSrc = src->data() + srcPos; + byte *pDest = dest->data(); + byte v; + bool carry = false; + uint16 currData, bitCtr, dx; + byte tableOffset; + uint16 tempReg1, tempReg2; + + // Handle splitting up 16 bytes into individual nibbles + for (int numBytes = 0; numBytes < 16; ++numBytes, ++pDest) { + // Split up next byte to pDest and pDest+0x10 + currData = *pSrc++; + *(pDest + 0x10) = currData & 0xf; + *pDest = (currData >> 4) & 0xf; + + // Split up next byte to pDest+0x20 and pDest+0x30 + currData = *pSrc++; + *(pDest + 0x30) = currData & 0xf; + *(pDest + 0x20) = (currData >> 4) & 0xf; + } + + pDest = (byte *) (dest->data() + 0x40); + currData = READ_BE_UINT16(pSrc); + pSrc += sizeof(uint16); + + bitCtr = 4; + *pDest = (currData >> 8) & 0xf0; + tableOffset = currData >> 12; + currData <<= 4; + dx = 1; + + for (;;) { + carry = false; + rcl(currData, carry); + if (--bitCtr == 0) { + GET_BYTE; + bitCtr = 8; + } + if (carry) goto loc_1441; + tableOffset = BX_VAL(0); + +loc_1439: + dx ^= 1; + if ((dx & 1) != 0) { + SET_HI_BYTE(dx, tableOffset << 4); + *pDest = dx >> 8; + } else { + *pDest++ |= tableOffset; + } + continue; + +loc_1441: + rcl(currData, carry); + if (--bitCtr == 0) { + GET_BYTE; + bitCtr = 8; + } + if (!carry) { + rcl(currData, carry); + if (--bitCtr == 0) { + GET_BYTE; + bitCtr = 8; + } + + if (!carry) { + tableOffset = BX_VAL(0x10); + } else { + tableOffset = BX_VAL(0x20); + } + goto loc_1439; + } + + rcl(currData, carry); + if (--bitCtr == 0) { + GET_BYTE; + bitCtr = 8; + } + if (!carry) { + tableOffset = BX_VAL(0x30); + goto loc_1439; + } + + SET_HI_BYTE(dx, currData >> 12); + carry = false; + for (int ctr = 0; ctr < 4; ++ctr) { + rcl(currData, carry); + if (--bitCtr == 0) { + GET_BYTE; + bitCtr = 8; + } + } + + byte dxHigh = dx >> 8; + if (dxHigh == BX_VAL(0)) { + tempReg1 = bitCtr; + tempReg2 = dx; + decode_data_2(pSrc, currData, bitCtr, dx, carry); + + SET_LO_BYTE(dx, dx >> 8); + decode_data_2(pSrc, currData, bitCtr, dx, carry); + SET_HI_BYTE(bitCtr, dx & 0xff); + SET_LO_BYTE(bitCtr, dx >> 8); + dx = tempReg2; + + if (bitCtr == 0) + // Exit out of infinite loop + break; + + } else if (dxHigh == BX_VAL(0x10)) { + tempReg1 = bitCtr; + decode_data_2(pSrc, currData, bitCtr, dx, carry); + bitCtr = dx >> 8; + + } else if (dxHigh == BX_VAL(0x20)) { + SET_HI_BYTE(dx, currData >> 10); + + for (v = 0; v < 6; ++v) { + rcl(currData, carry); + if (--bitCtr == 0) { + GET_BYTE; + bitCtr = 8; + } + } + + tempReg1 = bitCtr; + bitCtr = dx >> 8; + + } else if (dxHigh == BX_VAL(0x30)) { + SET_HI_BYTE(dx, currData >> 11); + + for (v = 0; v < 5; ++v) { + rcl(currData, carry); + if (--bitCtr == 0) { + GET_BYTE; + bitCtr = 8; + } + } + + tempReg1 = bitCtr; + bitCtr = dx >> 8; + + } else { + tableOffset = dx >> 8; + goto loc_1439; + } + + if ((dx & 1) == 1) { + *pDest++ |= tableOffset; + --bitCtr; + dx &= 0xfffe; + } + + SET_HI_BYTE(dx, tableOffset << 4); + tableOffset |= dx >> 8; + + v = bitCtr >> 1; + while (v-- > 0) *pDest++ = tableOffset; + + bitCtr &= 1; + if (bitCtr != 0) { + *pDest = tableOffset & 0xf0; + dx |= 1; //dx.l + } + + bitCtr = tempReg1; + tableOffset &= 0x0f; + } + + // Return number of bytes written + return pDest - dest->data(); +} + +} // end of namespace Lure |