summaryrefslogtreecommitdiff
path: root/utils/zenutils/source/shared/cenc.cpp
diff options
context:
space:
mode:
authorNicolas Pennequin <nicolas.pennequin@free.fr>2008-07-11 16:51:25 +0000
committerNicolas Pennequin <nicolas.pennequin@free.fr>2008-07-11 16:51:25 +0000
commitca5bb76d2b8f65aa97e50b633f828c1deb241526 (patch)
tree453a1b2de3a0dc0d0b2f7080d10d033bf8fbcdf1 /utils/zenutils/source/shared/cenc.cpp
parent141774be48940d56e3ad4dbf451d245b61d4f8b2 (diff)
downloadrockbox-ca5bb76d2b8f65aa97e50b633f828c1deb241526.zip
rockbox-ca5bb76d2b8f65aa97e50b633f828c1deb241526.tar.gz
rockbox-ca5bb76d2b8f65aa97e50b633f828c1deb241526.tar.bz2
rockbox-ca5bb76d2b8f65aa97e50b633f828c1deb241526.tar.xz
Delete the svn:executable property and set svn:eol-style to native for all those text files.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18012 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/zenutils/source/shared/cenc.cpp')
-rw-r--r--[-rwxr-xr-x]utils/zenutils/source/shared/cenc.cpp666
1 files changed, 333 insertions, 333 deletions
diff --git a/utils/zenutils/source/shared/cenc.cpp b/utils/zenutils/source/shared/cenc.cpp
index 932bee4..929a59b 100755..100644
--- a/utils/zenutils/source/shared/cenc.cpp
+++ b/utils/zenutils/source/shared/cenc.cpp
@@ -1,333 +1,333 @@
-/* zenutils - Utilities for working with creative firmwares.
- * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com>
- *
- * 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
- */
-
-#include "cenc.h"
-#include <firmware.h>
-#include <stdexcept>
-
-
-namespace {
-const byte CODE_MASK = 0xC0;
-const byte ARGS_MASK = 0x3F;
-
-const byte REPEAT_CODE = 0x00;
-const byte BLOCK_CODE = 0x40;
-const byte LONG_RUN_CODE = 0x80;
-const byte SHORT_RUN_CODE = 0xC0;
-
-const byte BLOCK_ARGS = 0x1F;
-const byte BLOCK_MODE = 0x20;
-
-
-void decode_run(byte* dst, word len, byte val,
- int& dstidx)
-{
- memset(dst + dstidx, val, len);
- dstidx += len;
-}
-
-void decode_pattern(byte* src, byte* dst,
- word len, int& srcidx, int& dstidx,
- bool bdecode, int npasses)
-{
- for (int i = 0; i < npasses; i++)
- {
- if (bdecode)
- {
- for (int j = 0; j < len; j++)
- {
- word c, d;
- c = src[srcidx + j];
- d = (c >> 5) & 7;
- c = (c << 3) & 0xF8;
- src[srcidx + j] = static_cast<byte>(c | d);
- }
- bdecode = false;
- }
- memcpy(dst + dstidx, src + srcidx, len);
- dstidx += len;
- }
- srcidx += len;
-}
-}; //namespace
-
-int zen::cenc_decode(byte* src, int srclen, byte* dst, int dstlen)
-{
- if (!src || !srclen || !dst || !dstlen)
- {
- throw std::invalid_argument("Invalid argument(s).");
- }
-
- int i = 0, j = 0;
- do
- {
- word c, d, e;
- c = src[i++];
- switch (c & CODE_MASK)
- {
- case REPEAT_CODE: // 2 bytes
- d = src[i++];
- d = d + 2;
-
- e = (c & ARGS_MASK) + 2;
-
- decode_pattern(src, dst, e, i, j, false, d);
- break;
-
- case BLOCK_CODE: // 1/2/3 bytes
- d = c & BLOCK_ARGS;
- if (!(c & BLOCK_MODE))
- {
- e = src[i++];
- e = (d << 8) + (e + 0x21);
-
- d = static_cast<word>(i ^ j);
- }
- else
- {
- e = d + 1;
-
- d = static_cast<word>(i ^ j);
- }
- if (d & 1)
- {
- i++;
- }
-
- decode_pattern(src, dst, e, i, j, true, 1);
- break;
-
- case LONG_RUN_CODE: // 3 bytes
- d = src[i++];
- e = ((c & ARGS_MASK) << 8) + (d + 0x42);
-
- d = src[i++];
- d = ((d & 7) << 5) | ((d >> 3) & 0x1F);
-
- decode_run(dst, e, static_cast<byte>(d), j);
- break;
-
- case SHORT_RUN_CODE: // 2 bytes
- d = src[i++];
- d = ((d & 3) << 6) | ((d >> 2) & 0x3F);
-
- e = (c & ARGS_MASK) + 2;
-
- decode_run(dst, e, static_cast<byte>(d), j);
- break;
- };
- } while (i < srclen && j < dstlen);
-
- return j;
-}
-
-namespace {
-int encode_run(byte* dst, int& dstidx, byte val, int len, int dstlen)
-{
- if (len < 2)
- throw std::invalid_argument("Length is too small.");
-
- int ret = 0;
- if (len <= 0x41)
- {
- if ((dstidx + 2) > dstlen)
- throw std::runtime_error("Not enough space to store run.");
-
- dst[dstidx++] = SHORT_RUN_CODE | (((len - 2) & ARGS_MASK));
- dst[dstidx++] = ((val >> 6) & 3) | ((val & 0x3F) << 2);
-
- ret = 2;
- }
- else if (len <= 0x4041)
- {
- if ((dstidx + 3) > dstlen)
- throw std::runtime_error("Not enough space to store run.");
-
- byte b1 = (len - 0x42) >> 8;
- byte b2 = (len - 0x42) & 0xFF;
-
- dst[dstidx++] = LONG_RUN_CODE | ((b1 & ARGS_MASK));
- dst[dstidx++] = b2;
- dst[dstidx++] = ((val >> 5) & 7) | ((val & 0x1F) << 3);
-
- ret = 3;
- }
- else
- {
- int long_count = len / 0x4041;
- int short_len = len % 0x4041;
- bool toosmall = short_len == 1;
-
- int run_len = 0x4041;
- for (int i = 0; i < long_count; i++)
- {
- if (toosmall && (i == (long_count-1)))
- {
- run_len--;
- toosmall = false;
- }
- int tmp = encode_run(dst, dstidx, val, run_len, dstlen);
- if (!tmp) return 0;
- ret += tmp;
- len -= run_len;
- }
-
- if (len)
- {
- int short_count = len / 0x41;
- int short_rest = short_count ? (len % 0x41) : 0;
- toosmall = short_rest == 1;
-
- run_len = 0x41;
- for (int i = 0; i < short_count; i++)
- {
- if (toosmall && (i == (short_count-1)))
- {
- run_len--;
- toosmall = false;
- }
- int tmp = encode_run(dst, dstidx, val, run_len, dstlen);
- if (!tmp) return 0;
- ret += tmp;
- len -= run_len;
- }
- int tmp = encode_run(dst, dstidx, val, len, dstlen);
- if (!tmp) return 0;
- ret += tmp;
- len -= len;
- }
- }
-
- return ret;
-}
-
-int encode_block(byte* dst, int& dstidx, byte* src, int& srcidx, int len,
- int dstlen)
-{
- if (len < 1)
- throw std::invalid_argument("Length is too small.");
-
- int startidx = dstidx;
- if (len < 0x21)
- {
- if ((dstidx + 2 + len) > dstlen)
- throw std::runtime_error("Not enough space to store block.");
-
- dst[dstidx++] = BLOCK_CODE | BLOCK_MODE | ((len - 1) & BLOCK_ARGS);
- if ((dstidx ^ srcidx) & 1)
- dst[dstidx++] = 0;
-
- for (int i = 0; i < len; i++)
- {
- byte c = src[srcidx++];
- byte d = (c & 7) << 5;
- c = (c & 0xF8) >> 3;
- dst[dstidx++] = c | d;
- }
- }
- else if (len < 0x2021)
- {
- if ((dstidx + 3 + len) > dstlen)
- throw std::runtime_error("Not enough space to store block.");
-
- dst[dstidx++] = BLOCK_CODE | (((len - 0x21) >> 8) & BLOCK_ARGS);
- dst[dstidx++] = (len - 0x21) & 0xFF;
- if ((dstidx ^ srcidx) & 1)
- dst[dstidx++] = 0;
-
- for (int i = 0; i < len; i++)
- {
- byte c = src[srcidx++];
- byte d = (c & 7) << 5;
- c = (c & 0xF8) >> 3;
- dst[dstidx++] = c | d;
- }
- }
- else
- {
- int longblocks = len / 0x2020;
- int rest = len % 0x2020;
- for (int i = 0; i < longblocks; i++)
- {
- int tmp = encode_block(dst, dstidx, src, srcidx, 0x2020, dstlen);
- if (!tmp) return 0;
- }
- if (rest)
- {
- int shortblocks = rest / 0x20;
- for (int i = 0; i < shortblocks; i++)
- {
- int tmp = encode_block(dst, dstidx, src, srcidx, 0x20, dstlen);
- if (!tmp) return 0;
- }
- rest = rest % 0x20;
- int tmp = encode_block(dst, dstidx, src, srcidx, rest, dstlen);
- if (!tmp) return 0;
- }
- }
-
- return (dstidx - startidx);
-}
-}; //namespace
-
-int zen::cenc_encode(byte* src, int srclen, byte* dst, int dstlen)
-{
- if (!src || !srclen || !dst || !dstlen)
- {
- throw std::invalid_argument("Invalid argument(s).");
- }
-
- int i = 0, j = 0, k = 0;
- word c, d, e;
- int runlen = 0;
- while (i < srclen && j < dstlen)
- {
- k = i;
- c = src[i++];
- runlen = 1;
- while (i < srclen && src[i] == c)
- {
- runlen++;
- i++;
- }
- if (runlen >= 2)
- {
- if (!encode_run(dst, j, c, runlen, dstlen))
- return 0;
- }
- else
- {
- runlen = 0;
- i = k;
- while (i < (srclen - 1) && (src[i] != src[i + 1]))
- {
- runlen++;
- i++;
- }
- if (i == (srclen - 1))
- {
- runlen++;
- i++;
- }
- if (!encode_block(dst, j, src, k, runlen, dstlen))
- return 0;
- }
- }
-
- return j;
-}
+/* zenutils - Utilities for working with creative firmwares.
+ * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com>
+ *
+ * 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
+ */
+
+#include "cenc.h"
+#include <firmware.h>
+#include <stdexcept>
+
+
+namespace {
+const byte CODE_MASK = 0xC0;
+const byte ARGS_MASK = 0x3F;
+
+const byte REPEAT_CODE = 0x00;
+const byte BLOCK_CODE = 0x40;
+const byte LONG_RUN_CODE = 0x80;
+const byte SHORT_RUN_CODE = 0xC0;
+
+const byte BLOCK_ARGS = 0x1F;
+const byte BLOCK_MODE = 0x20;
+
+
+void decode_run(byte* dst, word len, byte val,
+ int& dstidx)
+{
+ memset(dst + dstidx, val, len);
+ dstidx += len;
+}
+
+void decode_pattern(byte* src, byte* dst,
+ word len, int& srcidx, int& dstidx,
+ bool bdecode, int npasses)
+{
+ for (int i = 0; i < npasses; i++)
+ {
+ if (bdecode)
+ {
+ for (int j = 0; j < len; j++)
+ {
+ word c, d;
+ c = src[srcidx + j];
+ d = (c >> 5) & 7;
+ c = (c << 3) & 0xF8;
+ src[srcidx + j] = static_cast<byte>(c | d);
+ }
+ bdecode = false;
+ }
+ memcpy(dst + dstidx, src + srcidx, len);
+ dstidx += len;
+ }
+ srcidx += len;
+}
+}; //namespace
+
+int zen::cenc_decode(byte* src, int srclen, byte* dst, int dstlen)
+{
+ if (!src || !srclen || !dst || !dstlen)
+ {
+ throw std::invalid_argument("Invalid argument(s).");
+ }
+
+ int i = 0, j = 0;
+ do
+ {
+ word c, d, e;
+ c = src[i++];
+ switch (c & CODE_MASK)
+ {
+ case REPEAT_CODE: // 2 bytes
+ d = src[i++];
+ d = d + 2;
+
+ e = (c & ARGS_MASK) + 2;
+
+ decode_pattern(src, dst, e, i, j, false, d);
+ break;
+
+ case BLOCK_CODE: // 1/2/3 bytes
+ d = c & BLOCK_ARGS;
+ if (!(c & BLOCK_MODE))
+ {
+ e = src[i++];
+ e = (d << 8) + (e + 0x21);
+
+ d = static_cast<word>(i ^ j);
+ }
+ else
+ {
+ e = d + 1;
+
+ d = static_cast<word>(i ^ j);
+ }
+ if (d & 1)
+ {
+ i++;
+ }
+
+ decode_pattern(src, dst, e, i, j, true, 1);
+ break;
+
+ case LONG_RUN_CODE: // 3 bytes
+ d = src[i++];
+ e = ((c & ARGS_MASK) << 8) + (d + 0x42);
+
+ d = src[i++];
+ d = ((d & 7) << 5) | ((d >> 3) & 0x1F);
+
+ decode_run(dst, e, static_cast<byte>(d), j);
+ break;
+
+ case SHORT_RUN_CODE: // 2 bytes
+ d = src[i++];
+ d = ((d & 3) << 6) | ((d >> 2) & 0x3F);
+
+ e = (c & ARGS_MASK) + 2;
+
+ decode_run(dst, e, static_cast<byte>(d), j);
+ break;
+ };
+ } while (i < srclen && j < dstlen);
+
+ return j;
+}
+
+namespace {
+int encode_run(byte* dst, int& dstidx, byte val, int len, int dstlen)
+{
+ if (len < 2)
+ throw std::invalid_argument("Length is too small.");
+
+ int ret = 0;
+ if (len <= 0x41)
+ {
+ if ((dstidx + 2) > dstlen)
+ throw std::runtime_error("Not enough space to store run.");
+
+ dst[dstidx++] = SHORT_RUN_CODE | (((len - 2) & ARGS_MASK));
+ dst[dstidx++] = ((val >> 6) & 3) | ((val & 0x3F) << 2);
+
+ ret = 2;
+ }
+ else if (len <= 0x4041)
+ {
+ if ((dstidx + 3) > dstlen)
+ throw std::runtime_error("Not enough space to store run.");
+
+ byte b1 = (len - 0x42) >> 8;
+ byte b2 = (len - 0x42) & 0xFF;
+
+ dst[dstidx++] = LONG_RUN_CODE | ((b1 & ARGS_MASK));
+ dst[dstidx++] = b2;
+ dst[dstidx++] = ((val >> 5) & 7) | ((val & 0x1F) << 3);
+
+ ret = 3;
+ }
+ else
+ {
+ int long_count = len / 0x4041;
+ int short_len = len % 0x4041;
+ bool toosmall = short_len == 1;
+
+ int run_len = 0x4041;
+ for (int i = 0; i < long_count; i++)
+ {
+ if (toosmall && (i == (long_count-1)))
+ {
+ run_len--;
+ toosmall = false;
+ }
+ int tmp = encode_run(dst, dstidx, val, run_len, dstlen);
+ if (!tmp) return 0;
+ ret += tmp;
+ len -= run_len;
+ }
+
+ if (len)
+ {
+ int short_count = len / 0x41;
+ int short_rest = short_count ? (len % 0x41) : 0;
+ toosmall = short_rest == 1;
+
+ run_len = 0x41;
+ for (int i = 0; i < short_count; i++)
+ {
+ if (toosmall && (i == (short_count-1)))
+ {
+ run_len--;
+ toosmall = false;
+ }
+ int tmp = encode_run(dst, dstidx, val, run_len, dstlen);
+ if (!tmp) return 0;
+ ret += tmp;
+ len -= run_len;
+ }
+ int tmp = encode_run(dst, dstidx, val, len, dstlen);
+ if (!tmp) return 0;
+ ret += tmp;
+ len -= len;
+ }
+ }
+
+ return ret;
+}
+
+int encode_block(byte* dst, int& dstidx, byte* src, int& srcidx, int len,
+ int dstlen)
+{
+ if (len < 1)
+ throw std::invalid_argument("Length is too small.");
+
+ int startidx = dstidx;
+ if (len < 0x21)
+ {
+ if ((dstidx + 2 + len) > dstlen)
+ throw std::runtime_error("Not enough space to store block.");
+
+ dst[dstidx++] = BLOCK_CODE | BLOCK_MODE | ((len - 1) & BLOCK_ARGS);
+ if ((dstidx ^ srcidx) & 1)
+ dst[dstidx++] = 0;
+
+ for (int i = 0; i < len; i++)
+ {
+ byte c = src[srcidx++];
+ byte d = (c & 7) << 5;
+ c = (c & 0xF8) >> 3;
+ dst[dstidx++] = c | d;
+ }
+ }
+ else if (len < 0x2021)
+ {
+ if ((dstidx + 3 + len) > dstlen)
+ throw std::runtime_error("Not enough space to store block.");
+
+ dst[dstidx++] = BLOCK_CODE | (((len - 0x21) >> 8) & BLOCK_ARGS);
+ dst[dstidx++] = (len - 0x21) & 0xFF;
+ if ((dstidx ^ srcidx) & 1)
+ dst[dstidx++] = 0;
+
+ for (int i = 0; i < len; i++)
+ {
+ byte c = src[srcidx++];
+ byte d = (c & 7) << 5;
+ c = (c & 0xF8) >> 3;
+ dst[dstidx++] = c | d;
+ }
+ }
+ else
+ {
+ int longblocks = len / 0x2020;
+ int rest = len % 0x2020;
+ for (int i = 0; i < longblocks; i++)
+ {
+ int tmp = encode_block(dst, dstidx, src, srcidx, 0x2020, dstlen);
+ if (!tmp) return 0;
+ }
+ if (rest)
+ {
+ int shortblocks = rest / 0x20;
+ for (int i = 0; i < shortblocks; i++)
+ {
+ int tmp = encode_block(dst, dstidx, src, srcidx, 0x20, dstlen);
+ if (!tmp) return 0;
+ }
+ rest = rest % 0x20;
+ int tmp = encode_block(dst, dstidx, src, srcidx, rest, dstlen);
+ if (!tmp) return 0;
+ }
+ }
+
+ return (dstidx - startidx);
+}
+}; //namespace
+
+int zen::cenc_encode(byte* src, int srclen, byte* dst, int dstlen)
+{
+ if (!src || !srclen || !dst || !dstlen)
+ {
+ throw std::invalid_argument("Invalid argument(s).");
+ }
+
+ int i = 0, j = 0, k = 0;
+ word c, d, e;
+ int runlen = 0;
+ while (i < srclen && j < dstlen)
+ {
+ k = i;
+ c = src[i++];
+ runlen = 1;
+ while (i < srclen && src[i] == c)
+ {
+ runlen++;
+ i++;
+ }
+ if (runlen >= 2)
+ {
+ if (!encode_run(dst, j, c, runlen, dstlen))
+ return 0;
+ }
+ else
+ {
+ runlen = 0;
+ i = k;
+ while (i < (srclen - 1) && (src[i] != src[i + 1]))
+ {
+ runlen++;
+ i++;
+ }
+ if (i == (srclen - 1))
+ {
+ runlen++;
+ i++;
+ }
+ if (!encode_block(dst, j, src, k, runlen, dstlen))
+ return 0;
+ }
+ }
+
+ return j;
+}