summaryrefslogtreecommitdiff
path: root/utils/zenutils/source/shared/cenc.cpp
diff options
context:
space:
mode:
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 932bee4625..929a59b64d 100755..100644
--- a/utils/zenutils/source/shared/cenc.cpp
+++ b/utils/zenutils/source/shared/cenc.cpp
@@ -1,333 +1,333 @@
1/* zenutils - Utilities for working with creative firmwares. 1/* zenutils - Utilities for working with creative firmwares.
2 * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com> 2 * Copyright 2007 (c) Rasmus Ry <rasmus.ry{at}gmail.com>
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by 5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or 6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version. 7 * (at your option) any later version.
8 * 8 *
9 * This program is distributed in the hope that it will be useful, 9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software 15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */ 17 */
18 18
19#include "cenc.h" 19#include "cenc.h"
20#include <firmware.h> 20#include <firmware.h>
21#include <stdexcept> 21#include <stdexcept>
22 22
23 23
24namespace { 24namespace {
25const byte CODE_MASK = 0xC0; 25const byte CODE_MASK = 0xC0;
26const byte ARGS_MASK = 0x3F; 26const byte ARGS_MASK = 0x3F;
27 27
28const byte REPEAT_CODE = 0x00; 28const byte REPEAT_CODE = 0x00;
29const byte BLOCK_CODE = 0x40; 29const byte BLOCK_CODE = 0x40;
30const byte LONG_RUN_CODE = 0x80; 30const byte LONG_RUN_CODE = 0x80;
31const byte SHORT_RUN_CODE = 0xC0; 31const byte SHORT_RUN_CODE = 0xC0;
32 32
33const byte BLOCK_ARGS = 0x1F; 33const byte BLOCK_ARGS = 0x1F;
34const byte BLOCK_MODE = 0x20; 34const byte BLOCK_MODE = 0x20;
35 35
36 36
37void decode_run(byte* dst, word len, byte val, 37void decode_run(byte* dst, word len, byte val,
38 int& dstidx) 38 int& dstidx)
39{ 39{
40 memset(dst + dstidx, val, len); 40 memset(dst + dstidx, val, len);
41 dstidx += len; 41 dstidx += len;
42} 42}
43 43
44void decode_pattern(byte* src, byte* dst, 44void decode_pattern(byte* src, byte* dst,
45 word len, int& srcidx, int& dstidx, 45 word len, int& srcidx, int& dstidx,
46 bool bdecode, int npasses) 46 bool bdecode, int npasses)
47{ 47{
48 for (int i = 0; i < npasses; i++) 48 for (int i = 0; i < npasses; i++)
49 { 49 {
50 if (bdecode) 50 if (bdecode)
51 { 51 {
52 for (int j = 0; j < len; j++) 52 for (int j = 0; j < len; j++)
53 { 53 {
54 word c, d; 54 word c, d;
55 c = src[srcidx + j]; 55 c = src[srcidx + j];
56 d = (c >> 5) & 7; 56 d = (c >> 5) & 7;
57 c = (c << 3) & 0xF8; 57 c = (c << 3) & 0xF8;
58 src[srcidx + j] = static_cast<byte>(c | d); 58 src[srcidx + j] = static_cast<byte>(c | d);
59 } 59 }
60 bdecode = false; 60 bdecode = false;
61 } 61 }
62 memcpy(dst + dstidx, src + srcidx, len); 62 memcpy(dst + dstidx, src + srcidx, len);
63 dstidx += len; 63 dstidx += len;
64 } 64 }
65 srcidx += len; 65 srcidx += len;
66} 66}
67}; //namespace 67}; //namespace
68 68
69int zen::cenc_decode(byte* src, int srclen, byte* dst, int dstlen) 69int zen::cenc_decode(byte* src, int srclen, byte* dst, int dstlen)
70{ 70{
71 if (!src || !srclen || !dst || !dstlen) 71 if (!src || !srclen || !dst || !dstlen)
72 { 72 {
73 throw std::invalid_argument("Invalid argument(s)."); 73 throw std::invalid_argument("Invalid argument(s).");
74 } 74 }
75 75
76 int i = 0, j = 0; 76 int i = 0, j = 0;
77 do 77 do
78 { 78 {
79 word c, d, e; 79 word c, d, e;
80 c = src[i++]; 80 c = src[i++];
81 switch (c & CODE_MASK) 81 switch (c & CODE_MASK)
82 { 82 {
83 case REPEAT_CODE: // 2 bytes 83 case REPEAT_CODE: // 2 bytes
84 d = src[i++]; 84 d = src[i++];
85 d = d + 2; 85 d = d + 2;
86 86
87 e = (c & ARGS_MASK) + 2; 87 e = (c & ARGS_MASK) + 2;
88 88
89 decode_pattern(src, dst, e, i, j, false, d); 89 decode_pattern(src, dst, e, i, j, false, d);
90 break; 90 break;
91 91
92 case BLOCK_CODE: // 1/2/3 bytes 92 case BLOCK_CODE: // 1/2/3 bytes
93 d = c & BLOCK_ARGS; 93 d = c & BLOCK_ARGS;
94 if (!(c & BLOCK_MODE)) 94 if (!(c & BLOCK_MODE))
95 { 95 {
96 e = src[i++]; 96 e = src[i++];
97 e = (d << 8) + (e + 0x21); 97 e = (d << 8) + (e + 0x21);
98 98
99 d = static_cast<word>(i ^ j); 99 d = static_cast<word>(i ^ j);
100 } 100 }
101 else 101 else
102 { 102 {
103 e = d + 1; 103 e = d + 1;
104 104
105 d = static_cast<word>(i ^ j); 105 d = static_cast<word>(i ^ j);
106 } 106 }
107 if (d & 1) 107 if (d & 1)
108 { 108 {
109 i++; 109 i++;
110 } 110 }
111 111
112 decode_pattern(src, dst, e, i, j, true, 1); 112 decode_pattern(src, dst, e, i, j, true, 1);
113 break; 113 break;
114 114
115 case LONG_RUN_CODE: // 3 bytes 115 case LONG_RUN_CODE: // 3 bytes
116 d = src[i++]; 116 d = src[i++];
117 e = ((c & ARGS_MASK) << 8) + (d + 0x42); 117 e = ((c & ARGS_MASK) << 8) + (d + 0x42);
118 118
119 d = src[i++]; 119 d = src[i++];
120 d = ((d & 7) << 5) | ((d >> 3) & 0x1F); 120 d = ((d & 7) << 5) | ((d >> 3) & 0x1F);
121 121
122 decode_run(dst, e, static_cast<byte>(d), j); 122 decode_run(dst, e, static_cast<byte>(d), j);
123 break; 123 break;
124 124
125 case SHORT_RUN_CODE: // 2 bytes 125 case SHORT_RUN_CODE: // 2 bytes
126 d = src[i++]; 126 d = src[i++];
127 d = ((d & 3) << 6) | ((d >> 2) & 0x3F); 127 d = ((d & 3) << 6) | ((d >> 2) & 0x3F);
128 128
129 e = (c & ARGS_MASK) + 2; 129 e = (c & ARGS_MASK) + 2;
130 130
131 decode_run(dst, e, static_cast<byte>(d), j); 131 decode_run(dst, e, static_cast<byte>(d), j);
132 break; 132 break;
133 }; 133 };
134 } while (i < srclen && j < dstlen); 134 } while (i < srclen && j < dstlen);
135 135
136 return j; 136 return j;
137} 137}
138 138
139namespace { 139namespace {
140int encode_run(byte* dst, int& dstidx, byte val, int len, int dstlen) 140int encode_run(byte* dst, int& dstidx, byte val, int len, int dstlen)
141{ 141{
142 if (len < 2) 142 if (len < 2)
143 throw std::invalid_argument("Length is too small."); 143 throw std::invalid_argument("Length is too small.");
144 144
145 int ret = 0; 145 int ret = 0;
146 if (len <= 0x41) 146 if (len <= 0x41)
147 { 147 {
148 if ((dstidx + 2) > dstlen) 148 if ((dstidx + 2) > dstlen)
149 throw std::runtime_error("Not enough space to store run."); 149 throw std::runtime_error("Not enough space to store run.");
150 150
151 dst[dstidx++] = SHORT_RUN_CODE | (((len - 2) & ARGS_MASK)); 151 dst[dstidx++] = SHORT_RUN_CODE | (((len - 2) & ARGS_MASK));
152 dst[dstidx++] = ((val >> 6) & 3) | ((val & 0x3F) << 2); 152 dst[dstidx++] = ((val >> 6) & 3) | ((val & 0x3F) << 2);
153 153
154 ret = 2; 154 ret = 2;
155 } 155 }
156 else if (len <= 0x4041) 156 else if (len <= 0x4041)
157 { 157 {
158 if ((dstidx + 3) > dstlen) 158 if ((dstidx + 3) > dstlen)
159 throw std::runtime_error("Not enough space to store run."); 159 throw std::runtime_error("Not enough space to store run.");
160 160
161 byte b1 = (len - 0x42) >> 8; 161 byte b1 = (len - 0x42) >> 8;
162 byte b2 = (len - 0x42) & 0xFF; 162 byte b2 = (len - 0x42) & 0xFF;
163 163
164 dst[dstidx++] = LONG_RUN_CODE | ((b1 & ARGS_MASK)); 164 dst[dstidx++] = LONG_RUN_CODE | ((b1 & ARGS_MASK));
165 dst[dstidx++] = b2; 165 dst[dstidx++] = b2;
166 dst[dstidx++] = ((val >> 5) & 7) | ((val & 0x1F) << 3); 166 dst[dstidx++] = ((val >> 5) & 7) | ((val & 0x1F) << 3);
167 167
168 ret = 3; 168 ret = 3;
169 } 169 }
170 else 170 else
171 { 171 {
172 int long_count = len / 0x4041; 172 int long_count = len / 0x4041;
173 int short_len = len % 0x4041; 173 int short_len = len % 0x4041;
174 bool toosmall = short_len == 1; 174 bool toosmall = short_len == 1;
175 175
176 int run_len = 0x4041; 176 int run_len = 0x4041;
177 for (int i = 0; i < long_count; i++) 177 for (int i = 0; i < long_count; i++)
178 { 178 {
179 if (toosmall && (i == (long_count-1))) 179 if (toosmall && (i == (long_count-1)))
180 { 180 {
181 run_len--; 181 run_len--;
182 toosmall = false; 182 toosmall = false;
183 } 183 }
184 int tmp = encode_run(dst, dstidx, val, run_len, dstlen); 184 int tmp = encode_run(dst, dstidx, val, run_len, dstlen);
185 if (!tmp) return 0; 185 if (!tmp) return 0;
186 ret += tmp; 186 ret += tmp;
187 len -= run_len; 187 len -= run_len;
188 } 188 }
189 189
190 if (len) 190 if (len)
191 { 191 {
192 int short_count = len / 0x41; 192 int short_count = len / 0x41;
193 int short_rest = short_count ? (len % 0x41) : 0; 193 int short_rest = short_count ? (len % 0x41) : 0;
194 toosmall = short_rest == 1; 194 toosmall = short_rest == 1;
195 195
196 run_len = 0x41; 196 run_len = 0x41;
197 for (int i = 0; i < short_count; i++) 197 for (int i = 0; i < short_count; i++)
198 { 198 {
199 if (toosmall && (i == (short_count-1))) 199 if (toosmall && (i == (short_count-1)))
200 { 200 {
201 run_len--; 201 run_len--;
202 toosmall = false; 202 toosmall = false;
203 } 203 }
204 int tmp = encode_run(dst, dstidx, val, run_len, dstlen); 204 int tmp = encode_run(dst, dstidx, val, run_len, dstlen);
205 if (!tmp) return 0; 205 if (!tmp) return 0;
206 ret += tmp; 206 ret += tmp;
207 len -= run_len; 207 len -= run_len;
208 } 208 }
209 int tmp = encode_run(dst, dstidx, val, len, dstlen); 209 int tmp = encode_run(dst, dstidx, val, len, dstlen);
210 if (!tmp) return 0; 210 if (!tmp) return 0;
211 ret += tmp; 211 ret += tmp;
212 len -= len; 212 len -= len;
213 } 213 }
214 } 214 }
215 215
216 return ret; 216 return ret;
217} 217}
218 218
219int encode_block(byte* dst, int& dstidx, byte* src, int& srcidx, int len, 219int encode_block(byte* dst, int& dstidx, byte* src, int& srcidx, int len,
220 int dstlen) 220 int dstlen)
221{ 221{
222 if (len < 1) 222 if (len < 1)
223 throw std::invalid_argument("Length is too small."); 223 throw std::invalid_argument("Length is too small.");
224 224
225 int startidx = dstidx; 225 int startidx = dstidx;
226 if (len < 0x21) 226 if (len < 0x21)
227 { 227 {
228 if ((dstidx + 2 + len) > dstlen) 228 if ((dstidx + 2 + len) > dstlen)
229 throw std::runtime_error("Not enough space to store block."); 229 throw std::runtime_error("Not enough space to store block.");
230 230
231 dst[dstidx++] = BLOCK_CODE | BLOCK_MODE | ((len - 1) & BLOCK_ARGS); 231 dst[dstidx++] = BLOCK_CODE | BLOCK_MODE | ((len - 1) & BLOCK_ARGS);
232 if ((dstidx ^ srcidx) & 1) 232 if ((dstidx ^ srcidx) & 1)
233 dst[dstidx++] = 0; 233 dst[dstidx++] = 0;
234 234
235 for (int i = 0; i < len; i++) 235 for (int i = 0; i < len; i++)
236 { 236 {
237 byte c = src[srcidx++]; 237 byte c = src[srcidx++];
238 byte d = (c & 7) << 5; 238 byte d = (c & 7) << 5;
239 c = (c & 0xF8) >> 3; 239 c = (c & 0xF8) >> 3;
240 dst[dstidx++] = c | d; 240 dst[dstidx++] = c | d;
241 } 241 }
242 } 242 }
243 else if (len < 0x2021) 243 else if (len < 0x2021)
244 { 244 {
245 if ((dstidx + 3 + len) > dstlen) 245 if ((dstidx + 3 + len) > dstlen)
246 throw std::runtime_error("Not enough space to store block."); 246 throw std::runtime_error("Not enough space to store block.");
247 247
248 dst[dstidx++] = BLOCK_CODE | (((len - 0x21) >> 8) & BLOCK_ARGS); 248 dst[dstidx++] = BLOCK_CODE | (((len - 0x21) >> 8) & BLOCK_ARGS);
249 dst[dstidx++] = (len - 0x21) & 0xFF; 249 dst[dstidx++] = (len - 0x21) & 0xFF;
250 if ((dstidx ^ srcidx) & 1) 250 if ((dstidx ^ srcidx) & 1)
251 dst[dstidx++] = 0; 251 dst[dstidx++] = 0;
252 252
253 for (int i = 0; i < len; i++) 253 for (int i = 0; i < len; i++)
254 { 254 {
255 byte c = src[srcidx++]; 255 byte c = src[srcidx++];
256 byte d = (c & 7) << 5; 256 byte d = (c & 7) << 5;
257 c = (c & 0xF8) >> 3; 257 c = (c & 0xF8) >> 3;
258 dst[dstidx++] = c | d; 258 dst[dstidx++] = c | d;
259 } 259 }
260 } 260 }
261 else 261 else
262 { 262 {
263 int longblocks = len / 0x2020; 263 int longblocks = len / 0x2020;
264 int rest = len % 0x2020; 264 int rest = len % 0x2020;
265 for (int i = 0; i < longblocks; i++) 265 for (int i = 0; i < longblocks; i++)
266 { 266 {
267 int tmp = encode_block(dst, dstidx, src, srcidx, 0x2020, dstlen); 267 int tmp = encode_block(dst, dstidx, src, srcidx, 0x2020, dstlen);
268 if (!tmp) return 0; 268 if (!tmp) return 0;
269 } 269 }
270 if (rest) 270 if (rest)
271 { 271 {
272 int shortblocks = rest / 0x20; 272 int shortblocks = rest / 0x20;
273 for (int i = 0; i < shortblocks; i++) 273 for (int i = 0; i < shortblocks; i++)
274 { 274 {
275 int tmp = encode_block(dst, dstidx, src, srcidx, 0x20, dstlen); 275 int tmp = encode_block(dst, dstidx, src, srcidx, 0x20, dstlen);
276 if (!tmp) return 0; 276 if (!tmp) return 0;
277 } 277 }
278 rest = rest % 0x20; 278 rest = rest % 0x20;
279 int tmp = encode_block(dst, dstidx, src, srcidx, rest, dstlen); 279 int tmp = encode_block(dst, dstidx, src, srcidx, rest, dstlen);
280 if (!tmp) return 0; 280 if (!tmp) return 0;
281 } 281 }
282 } 282 }
283 283
284 return (dstidx - startidx); 284 return (dstidx - startidx);
285} 285}
286}; //namespace 286}; //namespace
287 287
288int zen::cenc_encode(byte* src, int srclen, byte* dst, int dstlen) 288int zen::cenc_encode(byte* src, int srclen, byte* dst, int dstlen)
289{ 289{
290 if (!src || !srclen || !dst || !dstlen) 290 if (!src || !srclen || !dst || !dstlen)
291 { 291 {
292 throw std::invalid_argument("Invalid argument(s)."); 292 throw std::invalid_argument("Invalid argument(s).");
293 } 293 }
294 294
295 int i = 0, j = 0, k = 0; 295 int i = 0, j = 0, k = 0;
296 word c, d, e; 296 word c, d, e;
297 int runlen = 0; 297 int runlen = 0;
298 while (i < srclen && j < dstlen) 298 while (i < srclen && j < dstlen)
299 { 299 {
300 k = i; 300 k = i;
301 c = src[i++]; 301 c = src[i++];
302 runlen = 1; 302 runlen = 1;
303 while (i < srclen && src[i] == c) 303 while (i < srclen && src[i] == c)
304 { 304 {
305 runlen++; 305 runlen++;
306 i++; 306 i++;
307 } 307 }
308 if (runlen >= 2) 308 if (runlen >= 2)
309 { 309 {
310 if (!encode_run(dst, j, c, runlen, dstlen)) 310 if (!encode_run(dst, j, c, runlen, dstlen))
311 return 0; 311 return 0;
312 } 312 }
313 else 313 else
314 { 314 {
315 runlen = 0; 315 runlen = 0;
316 i = k; 316 i = k;
317 while (i < (srclen - 1) && (src[i] != src[i + 1])) 317 while (i < (srclen - 1) && (src[i] != src[i + 1]))
318 { 318 {
319 runlen++; 319 runlen++;
320 i++; 320 i++;
321 } 321 }
322 if (i == (srclen - 1)) 322 if (i == (srclen - 1))
323 { 323 {
324 runlen++; 324 runlen++;
325 i++; 325 i++;
326 } 326 }
327 if (!encode_block(dst, j, src, k, runlen, dstlen)) 327 if (!encode_block(dst, j, src, k, runlen, dstlen))
328 return 0; 328 return 0;
329 } 329 }
330 } 330 }
331 331
332 return j; 332 return j;
333} 333}