aboutsummaryrefslogtreecommitdiff
path: root/kyra/codecs.cpp
diff options
context:
space:
mode:
authorJames Brown2004-10-15 06:06:47 +0000
committerJames Brown2004-10-15 06:06:47 +0000
commit8f65711a28b0cdedca29cdd1787b40546d448575 (patch)
treefeafc61c0bdbd529ef1eb52acf743033395f3547 /kyra/codecs.cpp
parent9e40ef7d29ccaca45708b39e1da92bbca088d6ac (diff)
downloadscummvm-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.cpp322
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
+