diff options
author | James Brown | 2004-10-15 06:06:47 +0000 |
---|---|---|
committer | James Brown | 2004-10-15 06:06:47 +0000 |
commit | 8f65711a28b0cdedca29cdd1787b40546d448575 (patch) | |
tree | feafc61c0bdbd529ef1eb52acf743033395f3547 /kyra/codecs.cpp | |
parent | 9e40ef7d29ccaca45708b39e1da92bbca088d6ac (diff) | |
download | scummvm-rg350-8f65711a28b0cdedca29cdd1787b40546d448575.tar.gz scummvm-rg350-8f65711a28b0cdedca29cdd1787b40546d448575.tar.bz2 scummvm-rg350-8f65711a28b0cdedca29cdd1787b40546d448575.zip |
Merge in some of LordHotos kyra code, with some changes.
It's still non-functional, but once I merge in some more of my local changes things should actually be moving a long a bit.
svn-id: r15554
Diffstat (limited to 'kyra/codecs.cpp')
-rw-r--r-- | kyra/codecs.cpp | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/kyra/codecs.cpp b/kyra/codecs.cpp new file mode 100644 index 0000000000..96404f0679 --- /dev/null +++ b/kyra/codecs.cpp @@ -0,0 +1,322 @@ +/* ScummVM - Kyrandia Interpreter + * Copyright (C) 2003-2004 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$ + * + */ + + +#include "stdafx.h" +#include "codecs.h" + +/***************************************************************************** + * decode.c - Decoding routines for format80, format40, format20 + * and format3 type graphics + * Author: Olaf van der spek + * Modified for FreeCNC by Kareem Dana + * Modified for Kyra by Jack Burton + * Format3 decoding added by Jack Burton + * Modified for ScummVM by Johannes Schickel + ****************************************************************************/ + +/** decompress format 80 compressed data. + * @param compressed data. + * @param pointer to output uncompressed data. + * @returns size of uncompressed data. + */ +namespace Kyra { +int Compression::decode80(const uint8* image_in, uint8* image_out) { + /* + 0 copy 0cccpppp p + 1 copy 10cccccc + 2 copy 11cccccc p p + 3 fill 11111110 c c v + 4 copy 11111111 c c p p + */ + + const uint8* copyp; + const uint8* readp = image_in; + uint8* writep = image_out; + uint16 code; + uint16 count; + +#ifdef SCUMM_BIG_ENDIAN + uint16 bigend; /* temporary big endian var */ +#endif + + while (1) + { + code = *readp++; + if (~code & 0x80) + { + //bit 7 = 0 + //command 0 (0cccpppp p): copy + count = (code >> 4) + 3; + copyp = writep - (((code & 0xf) << 8) + *readp++); + while (count--) + *writep++ = *copyp++; + } + else + { + //bit 7 = 1 + count = code & 0x3f; + if (~code & 0x40) + { + //bit 6 = 0 + if (!count) + //end of image + break; + //command 1 (10cccccc): copy + while (count--) + *writep++ = *readp++; + } + else + { + //bit 6 = 1 + if (count < 0x3e) + { + //command 2 (11cccccc p p): copy + count += 3; + +#ifdef SCUMM_BIG_ENDIAN + memcpy(&bigend, readp, 2); + copyp = (const uint8*)&image_out[*(const_cast<uint16*>((const uint16*)SWAP_BYTES_16(bigend))]; +#else + copyp = (const uint8*)&image_out[*(const_cast<uint16*>((const uint16*)readp))]; +#endif + + readp += 2; + while (count--) + *writep++ = *copyp++; + } + else if (count == 0x3e) + { + //command 3 (11111110 c c v): fill + +#ifdef SCUMM_BIG_ENDIAN + memset(&count, 0, sizeof(uint32)); + memcpy(&count, readp, 2); + count = const_cast<uint16*>((const uint16*)SWAP_BYTES_16(count)); +#else + count = *(const_cast<uint16*>((const uint16*)readp)); +#endif + readp += 2; + code = *readp++; + while (count--) + *writep++ = code; + } + else + { + //command 4 (copy 11111111 c c p p): copy + +#ifdef SCUMM_BIG_ENDIAN + memset(&count, 0, sizeof(uint32)); + memcpy(&count, readp, 2); + count = const_cast<uint16*>((const uint16*)SWAP_BYTES_16(count)); +#else + count = *(const_cast<uint16*>((const uint16*)readp)); +#endif + readp += 2; + +#ifdef SCUMM_BIG_ENDIAN + memcpy(&bigend, readp, 2); + copyp = (const uint8*)&image_out[*(const_cast<uint16*>((const uint16*)SWAP_BYTES_16(bigend))]; +#else + copyp = (const uint8*)&image_out[*(const_cast<uint16*>((const uint16*)readp))]; +#endif + readp += 2; + while (count--) + *writep++ = *copyp++; + } + } + } + } + + return (writep - image_out); +} + +/** decompress format 40 compressed data. + * @param compressed data. + * @param pointer to put uncompressed data in. + * @returns size of uncompressed data. + */ +int Compression::decode40(const uint8* image_in, uint8* image_out) { + /* + 0 fill 00000000 c v + 1 copy 0ccccccc + 2 skip 10000000 c 0ccccccc + 3 copy 10000000 c 10cccccc + 4 fill 10000000 c 11cccccc v + 5 skip 1ccccccc + */ + + const uint8* readp = image_in; + uint8* writep = image_out; + uint16 code; + uint16 count; + + while (1) { + code = *readp++; + if (~code & 0x80) + { + //bit 7 = 0 + if (!code) + { + //command 0 (00000000 c v): fill + count = *readp++; + code = *readp++; + while (count--) + *writep++ ^= code; + } + else + { + //command 1 (0ccccccc): copy + count = code; + while (count--) + *writep++ ^= *readp++; + } + + } + else + { + //bit 7 = 1 + if (!(count = code & 0x7f)) + { + +#ifdef SCUMM_BIG_ENDIAN + memset(&count, 0, sizeof(uint32)); + memcpy(&count, readp, 2); + count = const_cast<uint16*>((const uint16*)SWAP_BYTES_16(count)); +#else + count = *(const_cast<uint16*>((const uint16*)readp)); +#endif + readp += 2; + code = count >> 8; + if (~code & 0x80) + { + //bit 7 = 0 + //command 2 (10000000 c 0ccccccc): skip + if (!count) + // end of image + break; + writep += count; + } + else + { + //bit 7 = 1 + count &= 0x3fff; + if (~code & 0x40) + { + //bit 6 = 0 + //command 3 (10000000 c 10cccccc): copy + while (count--) + *writep++ ^= *readp++; + } + else + { + //bit 6 = 1 + //command 4 (10000000 c 11cccccc v): fill + code = *readp++; + while (count--) + *writep++ ^= code; + } + } + } + else //command 5 (1ccccccc): skip + writep += count; + } + } + return (writep - image_out); +} + +/** decompress format 3 compressed data. + * @param compressed data. + * @param pointer to put uncompressed data in. + * @param size of uncompressed image. + */ +int Compression::decode3(const uint8* image_in, uint8* image_out, int size) +{ /* Untested on BIG-Endian machines */ + + /* + 0 copy + 1 fill + 2 fill + */ + const uint8* readp = image_in; + uint8* writep = image_out; + int16 code; + int16 count; + + do { + code = *const_cast<int8*>((const int8*)readp++); + if (code > 0) // Copy + { + count = code ; + while (count--) + *writep++ = *readp++; + } + else if (code == 0) // Fill(1) + { + count = *(const_cast<uint16*>((const uint16*)readp)); + +#ifdef SCUMM_LITTLE_ENDIAN + count = SWAP_BYTES_16(count); +#endif + + readp += 2; + code = *readp++; + while (count--) + *writep++ = (uint8)code; + } + else if (code < 0) // Fill (2) + { + count = -code; + code = *readp++; + while (count--) + *writep++ = (uint8)code; + } + } while ((writep - image_out) < size); + + //and, to be uniform to other decomp. functions... + return (writep - image_out); +} + +/** decompress format 20 compressed data. + * @param compressed data. + * @param pointer to pu uncompressed data in. + * @param size of compressed data? + * @returns size of uncompressed data? + */ +int Compression::decode2(const uint8* s, uint8* d, int cb_s) { + const uint8* r = s; + const uint8* r_end = s + cb_s; + uint8* w = d; + while (r < r_end) { + int v = *r++; + if (v) + *w++ = v; + else { + v = *r++; + memset(w, 0, v); + w += v; + } + } + return w - d; + +} +} // end of namespace Kyra + |