replace vec.truncate(0) with vec.clear()
[nihav.git] / nihav-duck / src / codecs / truemotion1.rs
CommitLineData
1b8522d6 1use nihav_core::codecs::*;
2d90e8b6
KS
2use nihav_core::io::byteio::*;
3
4struct MaskState<'a> {
5 is_intra: bool,
6 pos: usize,
7 row_pos: usize,
8 row_size: usize,
9 mask: u8,
10 src: &'a [u8],
11}
12
13impl<'a> MaskState<'a> {
14 fn new(is_intra: bool, src: &'a [u8], row_size: usize) -> Self {
15 Self { is_intra, src, pos: 0, row_pos: 0, row_size, mask: 0x01 }
16 }
17 fn get_next(&mut self) -> bool {
18 if self.is_intra {
19 true
20 } else {
21 let res = (self.src[self.pos] & self.mask) == 0;
22 self.mask <<= 1;
23 if self.mask == 0 {
24 self.pos += 1;
25 self.mask = 0x01;
26 }
27 res
28 }
29 }
30 fn reset_row(&mut self) {
31 self.pos = self.row_pos;
32 self.mask = 0x01;
33 }
34 fn next_row(&mut self) {
35 self.row_pos += self.row_size;
36 self.reset_row();
37 }
38}
39
40struct IndexState<'a> {
41 src: &'a [u8],
42 pos: usize,
43 vec_idx: usize,
44 vec_subidx: usize,
45}
46
47impl<'a> IndexState<'a> {
48 fn new(src: &'a [u8]) -> Self {
49 Self { src, pos: 0, vec_idx: 0, vec_subidx: 0 }
50 }
51 fn get_next(&mut self) -> DecoderResult<()> {
52 validate!(self.pos < self.src.len());
53 self.vec_idx = self.src[self.pos] as usize;
54 self.vec_subidx = 0;
55 self.pos += 1;
56 Ok(())
57 }
58 fn get_pred(&self, dtab: &[[u32; 4]; 256]) -> u32 { dtab[self.vec_idx][self.vec_subidx] }
59 fn get_diff16(&mut self, dtab: &[[u32; 4]; 256]) -> DecoderResult<u32> {
60 let pred1 = self.get_pred(dtab);
61 let mut pred = pred1 >> 1;
62 if (pred1 & 1) != 0 {
63 self.get_next()?;
64 if self.vec_idx == 0 {
65 self.get_next()?;
66 let pred2 = self.get_pred(dtab);
67 pred = pred.wrapping_add((pred2 >> 1).wrapping_mul(5));
68 if (pred2 & 1) != 0 {
69 self.get_next()?;
70 } else {
71 self.vec_subidx += 1;
72 }
73 }
74 } else {
75 self.vec_subidx += 1;
76 }
77 Ok(pred)
78 }
79 fn get_diff16_noesc(&mut self, dtab: &[[u32; 4]; 256]) -> DecoderResult<u32> {
80 let pred1 = self.get_pred(dtab);
81 let pred = pred1 >> 1;
82 if (pred1 & 1) != 0 {
83 self.get_next()?;
84 } else {
85 self.vec_subidx += 1;
86 }
87 Ok(pred)
88 }
89 fn get_diff24(&mut self, dtab: &[[u32; 4]; 256], esctab: &[[u32; 4]; 256]) -> DecoderResult<u32> {
90 let pred1 = self.get_pred(dtab);
91 let mut pred = pred1 >> 1;
92 if (pred1 & 1) != 0 {
93 self.get_next()?;
94 if self.vec_idx == 0 {
95 self.get_next()?;
96 let pred2 = self.get_pred(esctab);
97 pred = pred.wrapping_add(pred2 >> 1);
98 if (pred2 & 1) != 0 {
99 self.get_next()?;
100 } else {
101 self.vec_subidx += 1;
102 }
103 }
104 } else {
105 self.vec_subidx += 1;
106 }
107 Ok(pred)
108 }
109}
110
111struct DeltaTables {
112 ydt: [[u32; 4]; 256],
113 cdt: [[u32; 4]; 256],
114 fat_ydt: [[u32; 4]; 256],
115 fat_cdt: [[u32; 4]; 256],
116 adt: [[u32; 4]; 256],
117}
118
119impl Default for DeltaTables {
120 fn default() -> Self {
121 Self {
122 ydt: [[0; 4]; 256],
123 cdt: [[0; 4]; 256],
124 fat_ydt: [[0; 4]; 256],
125 fat_cdt: [[0; 4]; 256],
126 adt: [[0; 4]; 256],
127 }
128 }
129}
130
131struct FrameBuf {
3fc28ece
KS
132 last16: Option<NAVideoBufferRef<u16>>,
133 last24: Option<NAVideoBufferRef<u8>>,
2d90e8b6
KS
134}
135
136impl FrameBuf {
3fc28ece
KS
137 fn set16(&mut self, buf: NAVideoBufferRef<u16>) { self.last16 = Some(buf); }
138 fn set24(&mut self, buf: NAVideoBufferRef<u8>) { self.last24 = Some(buf); }
139 fn get16(&mut self) -> Option<NAVideoBufferRef<u16>> {
2d90e8b6
KS
140 if let Some(ref mut frm) = self.last16 {
141 let newfrm = frm.copy_buffer();
3fc28ece
KS
142 *frm = newfrm.clone().into_ref();
143 Some(newfrm.into_ref())
2d90e8b6
KS
144 } else {
145 None
146 }
147 }
3fc28ece 148 fn get24(&mut self) -> Option<NAVideoBufferRef<u8>> {
2d90e8b6
KS
149 if let Some(ref mut frm) = self.last24 {
150 let newfrm = frm.copy_buffer();
3fc28ece
KS
151 *frm = newfrm.clone().into_ref();
152 Some(newfrm.into_ref())
2d90e8b6
KS
153 } else {
154 None
155 }
156 }
157 fn reset(&mut self) {
158 self.last16 = None;
159 self.last24 = None;
160 }
161}
162
163impl Default for FrameBuf {
164 fn default() -> Self {
165 Self { last16: None, last24: None }
166 }
167}
168
169#[derive(Default)]
170struct TM1Decoder {
2422d969 171 info: NACodecInfoRef,
2d90e8b6
KS
172 last_delta_set: usize,
173 last_table_idx: usize,
174 delta_tables: DeltaTables,
175 blk_w: usize,
176 blk_h: usize,
177 vert_pred: Vec<u32>,
178 lastframe: FrameBuf,
179}
180
181const RGB555_FORMAT: NAPixelFormaton = NAPixelFormaton { model: ColorModel::RGB(RGBSubmodel::RGB), components: 3,
182 comp_info: [
183 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 10, comp_offs: 0, next_elem: 2 }),
184 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 5, comp_offs: 0, next_elem: 2 }),
185 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 0, comp_offs: 0, next_elem: 2 }),
186 None, None],
187 elem_size: 2, be: false, alpha: false, palette: false };
188const BGR0_FORMAT: NAPixelFormaton = NAPixelFormaton { model: ColorModel::RGB(RGBSubmodel::RGB), components: 3,
189 comp_info: [
190 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 2, next_elem: 4 }),
191 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 1, next_elem: 4 }),
192 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 8, shift: 0, comp_offs: 0, next_elem: 4 }),
193 None, None],
194 elem_size: 4, be: false, alpha: false, palette: false };
195
196impl TM1Decoder {
197 fn new() -> Self { Self::default() }
198 fn set_delta_tables(&mut self, delta_set: usize, table_idx: usize, is_24bit: bool) {
199 if (self.last_delta_set == delta_set) && (self.last_table_idx == table_idx) { return; }
200 let ydt = &DUCK_Y_DELTAS[delta_set];
201 let yfdt = DUCK_Y_FAT_DELTAS[delta_set];
202 let cdt = &DUCK_C_DELTAS[delta_set];
203 let cfdt = DUCK_C_FAT_DELTAS[delta_set];
204 let vec = DUCK_VECTABLES[table_idx - 1];
205
8a7352c0 206 let mut vec_iter = vec.iter();
2d90e8b6
KS
207 for i in 0..256 {
208 let len = (*vec_iter.next().unwrap() as usize) >> 1;
209 for j in 0..len {
210 let pair = vec_iter.next().unwrap();
211 let lo = (pair >> 4) as usize;
212 let hi = (pair & 0xF) as usize;
213 if !is_24bit {
214 let d_lo = ydt[lo] + (ydt[lo] << 5) + (ydt[lo] << 10);
215 let d_hi = ydt[hi] + (ydt[hi] << 5) + (ydt[hi] << 10);
216 self.delta_tables.ydt[i][j] = ((d_lo + (d_hi << 16)) << 1) as u32;
217 let d_c = cdt[hi] + (cdt[lo] << 10);
218 self.delta_tables.cdt[i][j] = ((d_c + (d_c << 16)) << 1) as u32;
219 let d_a = lo + hi * 5;
220 self.delta_tables.adt[i][j] = ((d_a << 16) << 1) as u32;
221 } else {
222 self.delta_tables.ydt[i][j] = ((ydt [lo] + (ydt [hi] << 8) + (ydt [hi] << 16)) << 1) as u32;
223 self.delta_tables.fat_ydt[i][j] = ((yfdt[lo] + (yfdt[hi] << 8) + (yfdt[hi] << 16)) << 1) as u32;
224 self.delta_tables.cdt[i][j] = ((cdt [hi] + (cdt [lo] << 16)) << 1) as u32;
225 self.delta_tables.fat_cdt[i][j] = ((cfdt[hi] + (cfdt[lo] << 16)) << 1) as u32;
226 }
227 }
228 self.delta_tables.ydt[i][len - 1] |= 1;
229 self.delta_tables.cdt[i][len - 1] |= 1;
230 self.delta_tables.adt[i][len - 1] |= 1;
231 self.delta_tables.fat_ydt[i][len - 1] |= 1;
232 self.delta_tables.fat_cdt[i][len - 1] |= 1;
233 }
234
235 self.last_delta_set = delta_set;
236 self.last_table_idx = table_idx;
237 }
238 fn decode_16bit(&mut self, dst: &mut [u16], stride: usize, width: usize, height: usize, mask: &mut MaskState<'_>, index: &mut IndexState<'_>) -> DecoderResult<()> {
239 let mut off = 0;
240 index.get_next()?;
241 for y in 0..height {
242 let mut hor_pred: u32 = 0;
243 for x in (0..width).step_by(4) {
244 if mask.get_next() {
245 match y & 3 {
246 0 => {
247 let dc0 = index.get_diff16(&self.delta_tables.cdt)?;
248 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
249 hor_pred = hor_pred.wrapping_add(dc0);
250 hor_pred = hor_pred.wrapping_add(dy0);
251 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
252 self.vert_pred[(x >> 1) + 0] = cur;
253 dst[off + x + 0] = cur as u16;
254 dst[off + x + 1] = (cur >> 16) as u16;
255 if self.blk_w == 2 {
256 let dc1 = index.get_diff16(&self.delta_tables.cdt)?;
257 hor_pred = hor_pred.wrapping_add(dc1);
258 }
259 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
260 hor_pred = hor_pred.wrapping_add(dy1);
261 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
262 self.vert_pred[(x >> 1) + 1] = cur;
263 dst[off + x + 2] = cur as u16;
264 dst[off + x + 3] = (cur >> 16) as u16;
265 },
266 1 | 3 => {
267 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
268 hor_pred = hor_pred.wrapping_add(dy0);
269 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
270 self.vert_pred[(x >> 1) + 0] = cur;
271 dst[off + x + 0] = cur as u16;
272 dst[off + x + 1] = (cur >> 16) as u16;
273 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
274 hor_pred = hor_pred.wrapping_add(dy1);
275 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
276 self.vert_pred[(x >> 1) + 1] = cur;
277 dst[off + x + 2] = cur as u16;
278 dst[off + x + 3] = (cur >> 16) as u16;
279 },
280 2 => {
281 if self.blk_h == 2 {
282 let dc0 = index.get_diff16(&self.delta_tables.cdt)?;
283 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
284 hor_pred = hor_pred.wrapping_add(dc0);
285 hor_pred = hor_pred.wrapping_add(dy0);
286 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
287 self.vert_pred[(x >> 1) + 0] = cur;
288 dst[off + x + 0] = cur as u16;
289 dst[off + x + 1] = (cur >> 16) as u16;
290 if self.blk_w == 2 {
291 let dc1 = index.get_diff16(&self.delta_tables.cdt)?;
292 hor_pred = hor_pred.wrapping_add(dc1);
293 }
294 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
295 hor_pred = hor_pred.wrapping_add(dy1);
296 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
297 self.vert_pred[(x >> 1) + 1] = cur;
298 dst[off + x + 2] = cur as u16;
299 dst[off + x + 3] = (cur >> 16) as u16;
300 } else {
301 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
302 hor_pred = hor_pred.wrapping_add(dy0);
303 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
304 self.vert_pred[(x >> 1) + 0] = cur;
305 dst[off + x + 0] = cur as u16;
306 dst[off + x + 1] = (cur >> 16) as u16;
307 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
308 hor_pred = hor_pred.wrapping_add(dy1);
309 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
310 self.vert_pred[(x >> 1) + 1] = cur;
311 dst[off + x + 2] = cur as u16;
312 dst[off + x + 3] = (cur >> 16) as u16;
313 }
314 },
315 _ => unreachable!(),
316 };
317 } else {
8a7352c0 318 let cur = u32::from(dst[off + x + 0]) | (u32::from(dst[off + x + 1]) << 16);
2d90e8b6 319 self.vert_pred[(x >> 1) + 0] = cur;
8a7352c0 320 let cur = u32::from(dst[off + x + 2]) | (u32::from(dst[off + x + 3]) << 16);
2d90e8b6
KS
321 hor_pred = cur.wrapping_sub(self.vert_pred[(x >> 1) + 1]);
322 self.vert_pred[(x >> 1) + 1] = cur;
323 }
324 }
325 if (y & 3) != 3 {
326 mask.reset_row();
327 } else {
328 mask.next_row();
329 }
330 off += stride;
331 }
332 Ok(())
333 }
334 fn decode_sprite(&mut self, dst: &mut [u16], stride: usize, width: usize, height: usize, mask: &mut MaskState<'_>, index: &mut IndexState<'_>) -> DecoderResult<()> {
335 let mut off = 0;
336 let _ = index.get_next();
337 for y in 0..height {
338 let mut hor_pred: u32 = 0;
339 for x in (0..width).step_by(4) {
340 let is_tm = !mask.get_next();
341 let is_sprite = !mask.get_next();
342 if is_tm {
343 if (y & 3) == 0 {
344 let dc0 = index.get_diff16(&self.delta_tables.cdt)?;
345 hor_pred = hor_pred.wrapping_add(dc0);
346 }
347 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
348 hor_pred = hor_pred.wrapping_add(dy0);
349 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
350 self.vert_pred[(x >> 1) + 0] = cur;
351 dst[off + x + 0] = cur as u16;
352 dst[off + x + 1] = (cur >> 16) as u16;
353 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
354 hor_pred = hor_pred.wrapping_add(dy1);
355 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
356 self.vert_pred[(x >> 1) + 1] = cur;
357 dst[off + x + 2] = cur as u16;
358 dst[off + x + 3] = (cur >> 16) as u16;
359 } else if is_sprite {
360 if (y & 3) == 0 {
361 let dc0 = index.get_diff16(&self.delta_tables.cdt)?;
362 hor_pred = hor_pred.wrapping_add(dc0);
363 }
364 let dy0 = index.get_diff16(&self.delta_tables.ydt)?;
365 hor_pred = hor_pred.wrapping_add(dy0);
366 let _da0 = index.get_diff16_noesc(&self.delta_tables.adt)?;
367 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 0]);
368 self.vert_pred[(x >> 1) + 0] = cur;
369 dst[off + x + 0] = cur as u16;
370 dst[off + x + 1] = (cur >> 16) as u16;
371 let dy1 = index.get_diff16(&self.delta_tables.ydt)?;
372 hor_pred = hor_pred.wrapping_add(dy1);
373 let _da1 = index.get_diff16_noesc(&self.delta_tables.adt)?;
374 let cur = hor_pred.wrapping_add(self.vert_pred[(x >> 1) + 1]);
375 self.vert_pred[(x >> 1) + 1] = cur;
376 dst[off + x + 2] = cur as u16;
377 dst[off + x + 3] = (cur >> 16) as u16;
378 } else {
379 hor_pred = 0;
380 dst[off + x + 0] = 0;
381 dst[off + x + 1] = 0;
382 dst[off + x + 2] = 0;
383 dst[off + x + 3] = 0;
384 self.vert_pred[(x >> 1) + 0] = 0;
385 self.vert_pred[(x >> 1) + 1] = 0;
386 }
387 }
388 if (y & 3) != 3 {
389 mask.reset_row();
390 } else {
391 mask.next_row();
392 }
393 off += stride;
394 }
395 Ok(())
396 }
397 fn decode_24bit(&mut self, dst: &mut [u8], stride: usize, width: usize, height: usize, mask: &mut MaskState<'_>, index: &mut IndexState<'_>) -> DecoderResult<()> {
398 let mut off = 0;
399 index.get_next()?;
400 for y in 0..height {
401 let mut hor_pred: u32 = 0;
402 for x in (0..width).step_by(2) {
403 if mask.get_next() {
404 match y & 3 {
405 0 => {
406 let dc0 = index.get_diff24(&self.delta_tables.cdt, &self.delta_tables.fat_cdt)?;
407 let dy0 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
408 hor_pred = hor_pred.wrapping_add(dc0);
409 hor_pred = hor_pred.wrapping_add(dy0);
410 let cur = hor_pred.wrapping_add(self.vert_pred[x + 0]);
411 self.vert_pred[x + 0] = cur;
412 dst[off + x*4 + 0] = cur as u8;
413 dst[off + x*4 + 1] = (cur >> 8) as u8;
414 dst[off + x*4 + 2] = (cur >> 16) as u8;
415 dst[off + x*4 + 3] = 0;
416 if self.blk_w == 2 {
417 let dc1 = index.get_diff24(&self.delta_tables.cdt, &self.delta_tables.fat_cdt)?;
418 hor_pred = hor_pred.wrapping_add(dc1);
419 }
420 let dy1 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
421 hor_pred = hor_pred.wrapping_add(dy1);
422 let cur = hor_pred.wrapping_add(self.vert_pred[x + 1]);
423 self.vert_pred[x + 1] = cur;
424 dst[off + x*4 + 4] = cur as u8;
425 dst[off + x*4 + 5] = (cur >> 8) as u8;
426 dst[off + x*4 + 6] = (cur >> 16) as u8;
427 dst[off + x*4 + 7] = 0;
428 },
429 1 | 3 => {
430 let dy0 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
431 hor_pred = hor_pred.wrapping_add(dy0);
432 let cur = hor_pred.wrapping_add(self.vert_pred[x + 0]);
433 self.vert_pred[x + 0] = cur;
434 dst[off + x*4 + 0] = cur as u8;
435 dst[off + x*4 + 1] = (cur >> 8) as u8;
436 dst[off + x*4 + 2] = (cur >> 16) as u8;
437 dst[off + x*4 + 3] = 0;
438 let dy1 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
439 hor_pred = hor_pred.wrapping_add(dy1);
440 let cur = hor_pred.wrapping_add(self.vert_pred[x + 1]);
441 self.vert_pred[x + 1] = cur;
442 dst[off + x*4 + 4] = cur as u8;
443 dst[off + x*4 + 5] = (cur >> 8) as u8;
444 dst[off + x*4 + 6] = (cur >> 16) as u8;
445 dst[off + x*4 + 7] = 0;
446 },
447 2 => {
448 if self.blk_h == 2 {
449 let dc0 = index.get_diff24(&self.delta_tables.cdt, &self.delta_tables.fat_cdt)?;
450 let dy0 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
451 hor_pred = hor_pred.wrapping_add(dc0);
452 hor_pred = hor_pred.wrapping_add(dy0);
453 let cur = hor_pred.wrapping_add(self.vert_pred[x + 0]);
454 self.vert_pred[x + 0] = cur;
455 dst[off + x*4 + 0] = cur as u8;
456 dst[off + x*4 + 1] = (cur >> 8) as u8;
457 dst[off + x*4 + 2] = (cur >> 16) as u8;
458 dst[off + x*4 + 3] = 0;
459 if self.blk_w == 2 {
460 let dc1 = index.get_diff24(&self.delta_tables.cdt, &self.delta_tables.fat_cdt)?;
461 hor_pred = hor_pred.wrapping_add(dc1);
462 }
463 let dy1 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
464 hor_pred = hor_pred.wrapping_add(dy1);
465 let cur = hor_pred.wrapping_add(self.vert_pred[x + 1]);
466 self.vert_pred[x + 1] = cur;
467 dst[off + x*4 + 4] = cur as u8;
468 dst[off + x*4 + 5] = (cur >> 8) as u8;
469 dst[off + x*4 + 6] = (cur >> 16) as u8;
470 dst[off + x*4 + 7] = 0;
471 } else {
472 let dy0 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
473 hor_pred = hor_pred.wrapping_add(dy0);
474 let cur = hor_pred.wrapping_add(self.vert_pred[x + 0]);
475 self.vert_pred[x + 0] = cur;
476 dst[off + x*4 + 0] = cur as u8;
477 dst[off + x*4 + 1] = (cur >> 8) as u8;
478 dst[off + x*4 + 2] = (cur >> 16) as u8;
479 dst[off + x*4 + 3] = 0;
480 let dy1 = index.get_diff24(&self.delta_tables.ydt, &self.delta_tables.fat_ydt)?;
481 hor_pred = hor_pred.wrapping_add(dy1);
482 let cur = hor_pred.wrapping_add(self.vert_pred[x + 1]);
483 self.vert_pred[x + 1] = cur;
484 dst[off + x*4 + 4] = cur as u8;
485 dst[off + x*4 + 5] = (cur >> 8) as u8;
486 dst[off + x*4 + 6] = (cur >> 16) as u8;
487 dst[off + x*4 + 7] = 0;
488 }
489 },
490 _ => unreachable!(),
491 };
492 } else {
8a7352c0
KS
493 let cur = u32::from(dst[off + x*4 + 0])
494 | (u32::from(dst[off + x*4 + 1]) << 8)
495 | (u32::from(dst[off + x*4 + 2]) << 16)
496 | (u32::from(dst[off + x*4 + 3]) << 24);
2d90e8b6 497 self.vert_pred[x + 0] = cur;
8a7352c0
KS
498 let cur = u32::from(dst[off + x*4 + 4])
499 | (u32::from(dst[off + x*4 + 5]) << 8)
500 | (u32::from(dst[off + x*4 + 6]) << 16)
501 | (u32::from(dst[off + x*4 + 7]) << 24);
2d90e8b6
KS
502 hor_pred = cur.wrapping_sub(self.vert_pred[x + 1]);
503 self.vert_pred[x + 1] = cur;
504 }
505 }
506 if (y & 3) != 3 {
507 mask.reset_row();
508 } else {
509 mask.next_row();
510 }
511 off += stride;
512 }
513 Ok(())
514 }
515}
516
517impl NADecoder for TM1Decoder {
01613464 518 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
2d90e8b6
KS
519 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
520 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, YUV410_FORMAT));
2422d969 521 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
2d90e8b6
KS
522 Ok(())
523 } else {
524 Err(DecoderError::InvalidData)
525 }
526 }
01613464 527 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
2d90e8b6
KS
528 let src = pkt.get_buffer();
529 validate!(src.len() > 10);
530 let hdr_size = (src[0].rotate_left(3) & 0x7F) as usize;
531 validate!(hdr_size >= 12 && hdr_size < src.len());
532 let mut hdr: [u8; 127] = [0; 127];
533 for i in 1..hdr_size {
534 hdr[i - 1] = src[i] ^ src[i + 1];
535 }
536 let mut mr = MemoryReader::new_read(&hdr[0..hdr_size-1]);
537 let mut br = ByteReader::new(&mut mr);
538
539 let tm1type = br.read_byte()? as usize;
540 let delta_set = br.read_byte()? as usize;
541 let table_idx = br.read_byte()? as usize;
542 let height = br.read_u16le()? as usize;
543 let width = br.read_u16le()? as usize;
544 let _frameno = br.read_u16le()? as usize;
545 let version = br.read_byte()?;
546 let meta_type = br.read_byte()?;
547 validate!(width > 0 && height > 0);
548 let is_intra;
549 let mut is_sprite = false;
550 let mut spr_xoff = 0;
551 let mut spr_yoff = 0;
552 let mut spr_width = 0;
553 let mut spr_height = 0;
554 if version >= 2 {
555 validate!(meta_type <= 3);
556 if meta_type >= 2 {
557 let frameinfo = br.read_byte()?;
558 let _control = br.read_byte()?;
559
560 is_intra = ((frameinfo & 0x10) != 0) || ((frameinfo & 0x08) == 0);
561 } else {
562 is_intra = true;
563 }
564 if meta_type == 3 {
565 spr_xoff = br.read_u16le()? as usize;
566 spr_yoff = br.read_u16le()? as usize;
567 spr_width = br.read_u16le()? as usize;
568 spr_height = br.read_u16le()? as usize;
569 is_sprite = true;
570 }
571 } else {
572 is_intra = true;
573 }
574 validate!(tm1type < TM1_COMPR_TYPES.len());
575 let cinfo = TM1_COMPR_TYPES[tm1type];
576 if cinfo.is_none() {
577//check for missing ref
578 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::None);
579 frm.set_keyframe(false);
580 frm.set_frame_type(FrameType::Skip);
171860fc 581 return Ok(frm.into_ref());
2d90e8b6
KS
582 }
583 let compr_info = cinfo.unwrap();
584 let is_24bit = !is_sprite && compr_info.is_24bit;
585
586 let vec_idx = if ((tm1type & 1) != 0) && (meta_type > 0) { 1 } else { table_idx };
587 validate!((delta_set < DUCK_Y_DELTAS.len()) && (vec_idx > 0) && (vec_idx <= DUCK_VECTABLES.len()));
588 self.set_delta_tables(delta_set, vec_idx, is_24bit);
589
590 let out_width = if is_24bit { width >> 1 } else { width };
591 let mask_row_size = if is_sprite {
592 ((spr_width >> 2) + 3) >> 2
593 } else if is_intra {
594 0
595 } else {
596 ((width >> 2) + 7) >> 3
597 };
598 let mask_size = mask_row_size * (if is_sprite { spr_height >> 2 } else { height >> 2 });
599 let mask_bits = &src[hdr_size..][..mask_size];
600 let index_bytes = &src[hdr_size+mask_size..];
601 validate!(src.len() >= hdr_size + mask_size);
37952415 602 self.vert_pred.clear();
2d90e8b6
KS
603 self.vert_pred.resize(out_width, 0);
604
605 if is_intra || is_sprite {
606 let fmt = if is_24bit { BGR0_FORMAT } else { RGB555_FORMAT };
607 let myinfo = NAVideoInfo::new(out_width, height, false, fmt);
8a7352c0 608 let bufinfo = alloc_video_buffer(myinfo, 2)?;
2d90e8b6
KS
609 self.lastframe.reset();
610 if !is_24bit {
611 self.lastframe.set16(bufinfo.get_vbuf16().unwrap());
612 } else {
613 self.lastframe.set24(bufinfo.get_vbuf().unwrap());
614 }
615 }
616
617 self.blk_w = compr_info.block_w;
618 self.blk_h = compr_info.block_h;
619 let mut mask = MaskState::new(is_intra && !is_sprite, &mask_bits, mask_row_size);
620 let mut index = IndexState::new(&index_bytes);
621 let bufinfo;
622 if !is_24bit {
623 if let Some(mut buf) = self.lastframe.get16() {
624 let stride = buf.get_stride(0);
625 {
1a967e6b 626 let data = buf.get_data_mut().unwrap();
2d90e8b6
KS
627 if !is_sprite {
628 self.decode_16bit(data.as_mut_slice(), stride, out_width, height, &mut mask, &mut index)?;
629 } else {
630 validate!(spr_xoff + spr_width <= out_width);
631 validate!(spr_yoff + spr_height <= height);
632 for el in data.iter_mut() { *el = 0; }
633 let dst = &mut data[spr_xoff + spr_yoff * stride..];
634 self.decode_sprite(dst, stride, spr_width, spr_height, &mut mask, &mut index)?;
635 }
636 }
637 bufinfo = NABufferType::Video16(buf);
638 } else {
639 return Err(DecoderError::MissingReference);
640 }
8a7352c0
KS
641 } else if let Some(mut buf) = self.lastframe.get24() {
642 let stride = buf.get_stride(0);
643 {
644 let data = buf.get_data_mut().unwrap();
645 self.decode_24bit(data.as_mut_slice(), stride, out_width, height, &mut mask, &mut index)?;
2d90e8b6 646 }
8a7352c0
KS
647 bufinfo = NABufferType::VideoPacked(buf);
648 } else {
649 return Err(DecoderError::MissingReference);
2d90e8b6
KS
650 }
651
652 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
653 frm.set_keyframe(is_intra || is_sprite);
654 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
171860fc 655 Ok(frm.into_ref())
2d90e8b6 656 }
f9be4e75
KS
657 fn flush(&mut self) {
658 self.lastframe.reset();
659 }
2d90e8b6 660}
1b8522d6 661
7d57ae2f
KS
662impl NAOptionHandler for TM1Decoder {
663 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
664 fn set_options(&mut self, _options: &[NAOption]) { }
665 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
666}
667
08a1fab7 668pub fn get_decoder() -> Box<dyn NADecoder + Send> {
2d90e8b6 669 Box::new(TM1Decoder::new())
1b8522d6
KS
670}
671
2d90e8b6
KS
672#[cfg(test)]
673mod test {
674 use nihav_core::codecs::RegisteredDecoders;
675 use nihav_core::demuxers::RegisteredDemuxers;
ce742854 676 use nihav_codec_support::test::dec_video::*;
78fb6560 677 use crate::duck_register_all_decoders;
e64739f8 678 use nihav_commonfmt::generic_register_all_demuxers;
2d90e8b6
KS
679 #[test]
680 fn test_tm1() {
681 let mut dmx_reg = RegisteredDemuxers::new();
682 generic_register_all_demuxers(&mut dmx_reg);
683 let mut dec_reg = RegisteredDecoders::new();
78fb6560 684 duck_register_all_decoders(&mut dec_reg);
2d90e8b6 685
16b13997
KS
686 test_decoding("avi", "truemotion1", "assets/Duck/phant2-940.duk", Some(12), &dmx_reg, &dec_reg,
687 ExpectedTestResult::MD5Frames(vec![
688 [0x989e62b8, 0x5d85c23c, 0x1cffba6d, 0xe599f1c4],
689 [0xc4231321, 0x25561487, 0x9db11f57, 0x4faeb9a5],
690 [0x36e3a831, 0xdbd21f89, 0x0a446071, 0xf6d31ee7],
691 [0x0af640af, 0x64bc2bac, 0x0e95dd72, 0x9e55360b],
692 [0xbc9c5f8b, 0x6c06f2bc, 0x216f4129, 0x3a421337],
693 [0xd8ea7297, 0xce5f79fc, 0x46071f4c, 0xaed7fb7a],
694 [0x87617060, 0x72ce8df8, 0xde42eaa6, 0x804a6f45],
695 [0xfd8c45b3, 0xf424b683, 0xb4d6a9bd, 0xc622d0b9],
696 [0x6c233746, 0xba8ed68e, 0xc0ed0e85, 0xc99e1dc0],
697 [0x5842aac0, 0xd3d78242, 0x5da21218, 0xea1ed0ad],
698 [0xdea0db20, 0xe2ce3586, 0xf7386649, 0xecc374f9],
699 [0xb80ae9cb, 0x04eb938e, 0xd8a337ee, 0x0054b5ed],
700 [0xf8b80e1d, 0xd8eb3d6c, 0xa99b23ff, 0x562851a1]]));
701 test_decoding("avi", "truemotion1", "assets/Duck/SPRITES.AVI", Some(2), &dmx_reg, &dec_reg,
702 ExpectedTestResult::MD5([0xb89a4275, 0xf9797f5f, 0xe53c1ccd, 0xfa163e02]));
2d90e8b6 703 //let file = "assets/Duck/AVI-DUCK-dk3.duk";
16b13997 704 //let file = "assets/Duck/phant2-940.duk";
2d90e8b6
KS
705 //let file = "assets/Duck/bugsampler-m01-16bit.avi";
706 //let file = "assets/Duck/sonic3dblast_intro.avi";
707 //let file = "assets/Duck/BUTTONS.AVI";
708 //let file = "assets/Duck/SPRITES.AVI";
709 //let file = "assets/Duck/TRICORD.AVI";
16b13997 710 //test_file_decoding("avi", file, Some(42), true, false, None/*Some("tm1-")*/, &dmx_reg, &dec_reg);
2d90e8b6
KS
711 }
712}
713
714#[derive(Clone,Copy)]
715struct TM1ComprInfo {
716 is_24bit: bool,
717 block_w: usize,
718 block_h: usize,
719}
720
721const TM1_COMPR_TYPES: [Option<TM1ComprInfo>; 17] = [
722 None,
723 Some(TM1ComprInfo { is_24bit: false, block_w: 4, block_h: 4 }),
724 Some(TM1ComprInfo { is_24bit: false, block_w: 4, block_h: 4 }),
725 Some(TM1ComprInfo { is_24bit: false, block_w: 4, block_h: 2 }),
726 Some(TM1ComprInfo { is_24bit: false, block_w: 4, block_h: 2 }),
727 Some(TM1ComprInfo { is_24bit: false, block_w: 2, block_h: 4 }),
728 Some(TM1ComprInfo { is_24bit: false, block_w: 2, block_h: 4 }),
729 Some(TM1ComprInfo { is_24bit: false, block_w: 2, block_h: 2 }),
730 Some(TM1ComprInfo { is_24bit: false, block_w: 2, block_h: 2 }),
731 None,
732 Some(TM1ComprInfo { is_24bit: true, block_w: 4, block_h: 4 }),
733 None,
734 Some(TM1ComprInfo { is_24bit: true, block_w: 4, block_h: 2 }),
735 None,
736 Some(TM1ComprInfo { is_24bit: true, block_w: 2, block_h: 4 }),
737 None,
738 Some(TM1ComprInfo { is_24bit: true, block_w: 2, block_h: 2 }),
739];
740
741const DUCK_Y_DELTAS: [[i32; 8]; 4] = [
742 [ 0, -1, 1, -3, 3, -6, 6, -6 ],
743 [ 0, -1, 2, -3, 4, -6, 6, -6 ],
744 [ 2, -3, 10, -10, 23, -23, 47, -47 ],
745 [ 0, -2, 2, -8, 8, -18, 18, -40 ]
746];
747const DUCK_Y_FAT_DELTA3: [i32; 8] = [ 0, -15, 50, -50, 115, -115, 235, -235 ];
748const DUCK_Y_FAT_DELTA4: [i32; 8] = [ 0, 40, 80, -76, 160, -154, 236, -236 ];
749const DUCK_Y_FAT_DELTAS: [&[i32]; 4] = [
750 &DUCK_Y_FAT_DELTA3, &DUCK_Y_FAT_DELTA3, &DUCK_Y_FAT_DELTA3, &DUCK_Y_FAT_DELTA4
751];
752
753const DUCK_C_DELTAS: [[i32; 8]; 4] = [
754 [ 0, -1, 1, -2, 3, -4, 5, -4 ],
755 [ 0, -1, 1, -2, 3, -4, 5, -4 ],
756 [ 0, -4, 3, -16, 20, -32, 36, -32 ],
757 [ 0, -2, 2, -8, 8, -18, 18, -40 ]
758];
759const DUCK_C_FAT_DELTA3: [i32; 8] = [ 0, -20, 15, -80, 100, -160, 180, -160 ];
760const DUCK_C_FAT_DELTAS: [&[i32]; 4] = [
761 &DUCK_C_FAT_DELTA3, &DUCK_C_FAT_DELTA3, &DUCK_C_FAT_DELTA3, &DUCK_Y_FAT_DELTA4
762];
763
764const DUCK_VECTBL2: &[u8] = &[
7650x8,0x00,0x00,0x00,0x00,
7660x8,0x00,0x00,0x00,0x00,
7670x8,0x10,0x00,0x00,0x00,
7680x8,0x01,0x00,0x00,0x00,
7690x8,0x00,0x10,0x00,0x00,
7700x8,0x00,0x01,0x00,0x00,
7710x8,0x00,0x00,0x10,0x00,
7720x8,0x00,0x00,0x01,0x00,
7730x8,0x00,0x00,0x00,0x10,
7740x8,0x00,0x00,0x00,0x01,
7750x6,0x00,0x00,0x00,
7760x6,0x10,0x00,0x00,
7770x6,0x01,0x00,0x00,
7780x6,0x00,0x10,0x00,
7790x6,0x00,0x01,0x00,
7800x6,0x00,0x00,0x01,
7810x6,0x00,0x00,0x10,
7820x6,0x00,0x00,0x02,
7830x6,0x00,0x00,0x20,
7840x6,0x20,0x10,0x00,
7850x6,0x00,0x02,0x01,
7860x6,0x00,0x20,0x10,
7870x6,0x02,0x01,0x00,
7880x6,0x11,0x00,0x00,
7890x6,0x00,0x20,0x00,
7900x6,0x00,0x02,0x00,
7910x6,0x20,0x00,0x00,
7920x6,0x01,0x10,0x00,
7930x6,0x02,0x00,0x00,
7940x6,0x01,0x00,0x02,
7950x6,0x10,0x00,0x20,
7960x6,0x00,0x01,0x02,
7970x6,0x10,0x01,0x00,
7980x6,0x00,0x10,0x20,
7990x6,0x10,0x10,0x00,
8000x6,0x10,0x00,0x01,
8010x6,0x20,0x00,0x10,
8020x6,0x02,0x00,0x01,
8030x6,0x01,0x01,0x00,
8040x6,0x01,0x00,0x10,
8050x6,0x00,0x11,0x00,
8060x6,0x10,0x00,0x02,
8070x6,0x00,0x01,0x10,
8080x6,0x00,0x00,0x11,
8090x6,0x10,0x00,0x10,
8100x6,0x01,0x00,0x01,
8110x6,0x00,0x00,0x22,
8120x6,0x02,0x01,0x01,
8130x6,0x10,0x20,0x10,
8140x6,0x01,0x02,0x01,
8150x6,0x20,0x10,0x10,
8160x6,0x01,0x00,0x20,
8170x6,0x00,0x10,0x01,
8180x6,0x21,0x10,0x00,
8190x6,0x10,0x02,0x01,
8200x6,0x12,0x01,0x00,
8210x6,0x01,0x20,0x10,
8220x6,0x01,0x02,0x00,
8230x6,0x10,0x20,0x00,
8240x6,0x00,0x10,0x02,
8250x6,0x00,0x01,0x20,
8260x6,0x00,0x02,0x21,
8270x6,0x00,0x02,0x20,
8280x6,0x00,0x00,0x12,
8290x6,0x00,0x00,0x21,
8300x6,0x20,0x11,0x00,
8310x6,0x00,0x01,0x01,
8320x6,0x11,0x10,0x00,
8330x6,0x00,0x20,0x12,
8340x6,0x00,0x20,0x11,
8350x6,0x20,0x10,0x02,
8360x6,0x02,0x01,0x20,
8370x6,0x00,0x22,0x11,
8380x6,0x00,0x10,0x10,
8390x6,0x02,0x11,0x00,
8400x6,0x00,0x21,0x10,
8410x6,0x00,0x02,0x03,
8420x6,0x20,0x10,0x01,
8430x6,0x00,0x12,0x01,
8440x4,0x11,0x00,
8450x4,0x00,0x22,
8460x4,0x20,0x00,
8470x4,0x01,0x10,
8480x4,0x02,0x20,
8490x4,0x00,0x20,
8500x4,0x02,0x00,
8510x4,0x10,0x01,
8520x4,0x00,0x11,
8530x4,0x02,0x01,
8540x4,0x02,0x21,
8550x4,0x00,0x02,
8560x4,0x20,0x02,
8570x4,0x01,0x01,
8580x4,0x10,0x10,
8590x4,0x10,0x02,
8600x4,0x22,0x00,
8610x4,0x10,0x00,
8620x4,0x01,0x00,
8630x4,0x21,0x00,
8640x4,0x12,0x00,
8650x4,0x00,0x10,
8660x4,0x20,0x12,
8670x4,0x01,0x11,
8680x4,0x00,0x01,
8690x4,0x01,0x02,
8700x4,0x11,0x02,
8710x4,0x11,0x01,
8720x4,0x10,0x20,
8730x4,0x20,0x01,
8740x4,0x22,0x11,
8750x4,0x00,0x12,
8760x4,0x20,0x10,
8770x4,0x22,0x01,
8780x4,0x01,0x20,
8790x4,0x00,0x21,
8800x4,0x10,0x11,
8810x4,0x21,0x10,
8820x4,0x10,0x22,
8830x4,0x02,0x03,
8840x4,0x12,0x01,
8850x4,0x20,0x11,
8860x4,0x11,0x10,
8870x4,0x20,0x30,
8880x4,0x11,0x20,
8890x4,0x02,0x10,
8900x4,0x22,0x10,
8910x4,0x11,0x11,
8920x4,0x30,0x20,
8930x4,0x30,0x00,
8940x4,0x01,0x22,
8950x4,0x01,0x12,
8960x4,0x02,0x11,
8970x4,0x03,0x02,
8980x4,0x03,0x00,
8990x4,0x10,0x21,
9000x4,0x12,0x20,
9010x4,0x00,0x00,
9020x4,0x12,0x21,
9030x4,0x21,0x11,
9040x4,0x02,0x22,
9050x4,0x10,0x12,
9060x4,0x31,0x00,
9070x4,0x20,0x20,
9080x4,0x00,0x03,
9090x4,0x02,0x02,
9100x4,0x22,0x20,
9110x4,0x01,0x21,
9120x4,0x21,0x02,
9130x4,0x21,0x12,
9140x4,0x11,0x22,
9150x4,0x00,0x30,
9160x4,0x12,0x11,
9170x4,0x20,0x22,
9180x4,0x31,0x20,
9190x4,0x21,0x30,
9200x4,0x22,0x02,
9210x4,0x22,0x22,
9220x4,0x20,0x31,
9230x4,0x13,0x02,
9240x4,0x03,0x10,
9250x4,0x11,0x12,
9260x4,0x00,0x13,
9270x4,0x21,0x01,
9280x4,0x12,0x03,
9290x4,0x13,0x00,
9300x4,0x13,0x10,
9310x4,0x02,0x13,
9320x4,0x30,0x01,
9330x4,0x12,0x10,
9340x4,0x22,0x13,
9350x4,0x03,0x12,
9360x4,0x31,0x01,
9370x4,0x30,0x22,
9380x4,0x00,0x31,
9390x4,0x01,0x31,
9400x4,0x02,0x23,
9410x4,0x01,0x30,
9420x4,0x11,0x21,
9430x4,0x22,0x21,
9440x4,0x01,0x13,
9450x4,0x10,0x03,
9460x4,0x22,0x03,
9470x4,0x30,0x21,
9480x4,0x21,0x31,
9490x4,0x33,0x00,
9500x4,0x13,0x12,
9510x4,0x11,0x31,
9520x4,0x30,0x02,
9530x4,0x12,0x02,
9540x4,0x11,0x13,
9550x4,0x12,0x22,
9560x4,0x20,0x32,
9570x4,0x10,0x13,
9580x4,0x22,0x31,
9590x4,0x21,0x20,
9600x4,0x01,0x33,
9610x4,0x33,0x10,
9620x4,0x20,0x13,
9630x4,0x31,0x22,
9640x4,0x13,0x30,
9650x4,0x01,0x03,
9660x4,0x11,0x33,
9670x4,0x20,0x21,
9680x4,0x13,0x31,
9690x4,0x03,0x22,
9700x4,0x31,0x02,
9710x4,0x00,0x24,
9720x2,0x00,
9730x2,0x10,
9740x2,0x20,
9750x2,0x30,
9760x2,0x40,
9770x2,0x50,
9780x2,0x60,
9790x2,0x01,
9800x2,0x11,
9810x2,0x21,
9820x2,0x31,
9830x2,0x41,
9840x2,0x51,
9850x2,0x61,
9860x2,0x02,
9870x2,0x12,
9880x2,0x22,
9890x2,0x32,
9900x2,0x42,
9910x2,0x52,
9920x2,0x62,
9930x2,0x03,
9940x2,0x13,
9950x2,0x23,
9960x2,0x33,
9970x2,0x43,
9980x2,0x53,
9990x2,0x63,
10000x2,0x04,
10010x2,0x14,
10020x2,0x24,
10030x2,0x34,
10040x2,0x44,
10050x2,0x54,
10060x2,0x64,
10070x2,0x05,
10080x2,0x15,
10090x2,0x25,
10100x2,0x35,
10110x2,0x45,
10120x2,0x55,
10130x2,0x65,
10140x2,0x06,
10150x2,0x16,
10160x2,0x26,
10170x2,0x36,
10180x2,0x46,
10190x2,0x56,
10200x2,0x66
1021];
1022
1023const DUCK_VECTBL3: &[u8] = &[
10240x6,0x00,0x00,0x00,
10250x6,0x00,0x00,0x00,
10260x6,0x00,0x00,0x01,
10270x6,0x00,0x00,0x10,
10280x6,0x00,0x00,0x11,
10290x6,0x00,0x01,0x00,
10300x6,0x00,0x01,0x01,
10310x6,0x00,0x01,0x10,
10320x6,0x00,0x01,0x11,
10330x6,0x00,0x10,0x00,
10340x6,0x00,0x10,0x01,
10350x6,0x00,0x10,0x10,
10360x6,0x00,0x10,0x11,
10370x6,0x00,0x11,0x00,
10380x6,0x00,0x11,0x01,
10390x6,0x00,0x11,0x10,
10400x6,0x00,0x11,0x11,
10410x6,0x01,0x00,0x00,
10420x6,0x01,0x00,0x01,
10430x6,0x01,0x00,0x10,
10440x6,0x01,0x00,0x11,
10450x6,0x01,0x01,0x00,
10460x6,0x01,0x01,0x01,
10470x6,0x01,0x01,0x10,
10480x6,0x01,0x01,0x11,
10490x6,0x01,0x10,0x00,
10500x6,0x01,0x10,0x01,
10510x6,0x01,0x10,0x10,
10520x6,0x01,0x10,0x11,
10530x6,0x01,0x11,0x00,
10540x6,0x01,0x11,0x01,
10550x6,0x01,0x11,0x10,
10560x6,0x01,0x11,0x11,
10570x6,0x10,0x00,0x00,
10580x6,0x10,0x00,0x01,
10590x6,0x10,0x00,0x10,
10600x6,0x10,0x00,0x11,
10610x6,0x10,0x01,0x00,
10620x6,0x10,0x01,0x01,
10630x6,0x10,0x01,0x10,
10640x6,0x10,0x01,0x11,
10650x6,0x10,0x10,0x00,
10660x6,0x10,0x10,0x01,
10670x6,0x10,0x10,0x10,
10680x6,0x10,0x10,0x11,
10690x6,0x10,0x11,0x00,
10700x6,0x10,0x11,0x01,
10710x6,0x10,0x11,0x10,
10720x6,0x10,0x11,0x11,
10730x6,0x11,0x00,0x00,
10740x6,0x11,0x00,0x01,
10750x6,0x11,0x00,0x10,
10760x6,0x11,0x00,0x11,
10770x6,0x11,0x01,0x00,
10780x6,0x11,0x01,0x01,
10790x6,0x11,0x01,0x10,
10800x6,0x11,0x01,0x11,
10810x6,0x11,0x10,0x00,
10820x6,0x11,0x10,0x01,
10830x6,0x11,0x10,0x10,
10840x6,0x11,0x10,0x11,
10850x6,0x11,0x11,0x00,
10860x6,0x11,0x11,0x01,
10870x6,0x11,0x11,0x10,
10880x4,0x00,0x00,
10890x4,0x00,0x01,
10900x4,0x00,0x02,
10910x4,0x00,0x03,
10920x4,0x00,0x10,
10930x4,0x00,0x11,
10940x4,0x00,0x12,
10950x4,0x00,0x13,
10960x4,0x00,0x20,
10970x4,0x00,0x21,
10980x4,0x00,0x22,
10990x4,0x00,0x23,
11000x4,0x00,0x30,
11010x4,0x00,0x31,
11020x4,0x00,0x32,
11030x4,0x00,0x33,
11040x4,0x01,0x00,
11050x4,0x01,0x01,
11060x4,0x01,0x02,
11070x4,0x01,0x03,
11080x4,0x01,0x10,
11090x4,0x01,0x11,
11100x4,0x01,0x12,
11110x4,0x01,0x13,
11120x4,0x01,0x20,
11130x4,0x01,0x21,
11140x4,0x01,0x22,
11150x4,0x01,0x23,
11160x4,0x01,0x30,
11170x4,0x01,0x31,
11180x4,0x01,0x32,
11190x4,0x01,0x33,
11200x4,0x02,0x00,
11210x4,0x02,0x01,
11220x4,0x02,0x02,
11230x4,0x02,0x03,
11240x4,0x02,0x10,
11250x4,0x02,0x11,
11260x4,0x02,0x12,
11270x4,0x02,0x13,
11280x4,0x02,0x20,
11290x4,0x02,0x21,
11300x4,0x02,0x22,
11310x4,0x02,0x23,
11320x4,0x02,0x30,
11330x4,0x02,0x31,
11340x4,0x02,0x32,
11350x4,0x02,0x33,
11360x4,0x03,0x00,
11370x4,0x03,0x01,
11380x4,0x03,0x02,
11390x4,0x03,0x03,
11400x4,0x03,0x10,
11410x4,0x03,0x11,
11420x4,0x03,0x12,
11430x4,0x03,0x13,
11440x4,0x03,0x20,
11450x4,0x03,0x21,
11460x4,0x03,0x22,
11470x4,0x03,0x23,
11480x4,0x03,0x30,
11490x4,0x03,0x31,
11500x4,0x03,0x32,
11510x4,0x03,0x33,
11520x4,0x10,0x00,
11530x4,0x10,0x01,
11540x4,0x10,0x02,
11550x4,0x10,0x03,
11560x4,0x10,0x10,
11570x4,0x10,0x11,
11580x4,0x10,0x12,
11590x4,0x10,0x13,
11600x4,0x10,0x20,
11610x4,0x10,0x21,
11620x4,0x10,0x22,
11630x4,0x10,0x23,
11640x4,0x10,0x30,
11650x4,0x10,0x31,
11660x4,0x10,0x32,
11670x4,0x10,0x33,
11680x4,0x11,0x00,
11690x4,0x11,0x01,
11700x4,0x11,0x02,
11710x4,0x11,0x03,
11720x4,0x11,0x10,
11730x4,0x11,0x11,
11740x4,0x11,0x12,
11750x4,0x11,0x13,
11760x4,0x11,0x20,
11770x4,0x11,0x21,
11780x4,0x11,0x22,
11790x4,0x11,0x23,
11800x4,0x11,0x30,
11810x4,0x11,0x31,
11820x4,0x11,0x32,
11830x4,0x11,0x33,
11840x4,0x12,0x00,
11850x4,0x12,0x01,
11860x4,0x12,0x02,
11870x4,0x12,0x03,
11880x4,0x12,0x10,
11890x4,0x12,0x11,
11900x4,0x12,0x12,
11910x4,0x12,0x13,
11920x4,0x12,0x20,
11930x4,0x12,0x21,
11940x4,0x12,0x22,
11950x4,0x12,0x23,
11960x4,0x12,0x30,
11970x4,0x12,0x31,
11980x4,0x12,0x32,
11990x4,0x12,0x33,
12000x4,0x13,0x00,
12010x4,0x13,0x01,
12020x4,0x13,0x02,
12030x4,0x13,0x03,
12040x4,0x13,0x10,
12050x4,0x13,0x11,
12060x4,0x13,0x12,
12070x4,0x13,0x13,
12080x4,0x13,0x20,
12090x4,0x13,0x21,
12100x4,0x13,0x22,
12110x4,0x13,0x23,
12120x4,0x13,0x30,
12130x4,0x13,0x31,
12140x4,0x13,0x32,
12150x4,0x13,0x33,
12160x2,0x00,
12170x2,0x10,
12180x2,0x20,
12190x2,0x30,
12200x2,0x40,
12210x2,0x50,
12220x2,0x60,
12230x2,0x70,
12240x2,0x01,
12250x2,0x11,
12260x2,0x21,
12270x2,0x31,
12280x2,0x41,
12290x2,0x51,
12300x2,0x61,
12310x2,0x71,
12320x2,0x02,
12330x2,0x12,
12340x2,0x22,
12350x2,0x32,
12360x2,0x42,
12370x2,0x52,
12380x2,0x62,
12390x2,0x72,
12400x2,0x03,
12410x2,0x13,
12420x2,0x23,
12430x2,0x33,
12440x2,0x43,
12450x2,0x53,
12460x2,0x63,
12470x2,0x73,
12480x2,0x04,
12490x2,0x14,
12500x2,0x24,
12510x2,0x34,
12520x2,0x44,
12530x2,0x54,
12540x2,0x64,
12550x2,0x74,
12560x2,0x05,
12570x2,0x15,
12580x2,0x25,
12590x2,0x35,
12600x2,0x45,
12610x2,0x55,
12620x2,0x65,
12630x2,0x75,
12640x2,0x06,
12650x2,0x16,
12660x2,0x26,
12670x2,0x36,
12680x2,0x46,
12690x2,0x56,
12700x2,0x66,
12710x2,0x76,
12720x2,0x07,
12730x2,0x17,
12740x2,0x27,
12750x2,0x37,
12760x2,0x47,
12770x2,0x57,
12780x2,0x67,
12790x2,0x77
1280];
1281
1282const DUCK_VECTBL4: &[u8] = &[
12830x8,0x00,0x00,0x00,0x00,
12840x8,0x00,0x00,0x00,0x00,
12850x8,0x20,0x00,0x00,0x00,
12860x8,0x00,0x00,0x00,0x01,
12870x8,0x10,0x00,0x00,0x00,
12880x8,0x00,0x00,0x00,0x02,
12890x8,0x01,0x00,0x00,0x00,
12900x8,0x00,0x00,0x00,0x10,
12910x8,0x02,0x00,0x00,0x00,
12920x6,0x00,0x00,0x00,
12930x6,0x20,0x00,0x00,
12940x6,0x00,0x00,0x01,
12950x6,0x10,0x00,0x00,
12960x6,0x00,0x00,0x02,
12970x6,0x00,0x10,0x00,
12980x6,0x00,0x20,0x00,
12990x6,0x00,0x02,0x00,
13000x6,0x00,0x01,0x00,
13010x6,0x01,0x00,0x00,
13020x6,0x00,0x00,0x20,
13030x6,0x02,0x00,0x00,
13040x6,0x00,0x00,0x10,
13050x6,0x10,0x00,0x20,
13060x6,0x01,0x00,0x02,
13070x6,0x20,0x00,0x10,
13080x6,0x02,0x00,0x01,
13090x6,0x20,0x10,0x00,
13100x6,0x00,0x12,0x00,
13110x6,0x00,0x02,0x01,
13120x6,0x02,0x01,0x00,
13130x6,0x00,0x21,0x00,
13140x6,0x00,0x01,0x02,
13150x6,0x00,0x20,0x10,
13160x6,0x00,0x00,0x21,
13170x6,0x00,0x00,0x12,
13180x6,0x00,0x01,0x20,
13190x6,0x12,0x00,0x00,
13200x6,0x00,0x10,0x20,
13210x6,0x01,0x20,0x00,
13220x6,0x02,0x10,0x00,
13230x6,0x10,0x20,0x00,
13240x6,0x01,0x02,0x00,
13250x6,0x21,0x00,0x00,
13260x6,0x00,0x02,0x10,
13270x6,0x20,0x01,0x00,
13280x6,0x00,0x22,0x00,
13290x6,0x10,0x02,0x00,
13300x6,0x00,0x10,0x02,
13310x6,0x11,0x00,0x00,
13320x6,0x00,0x11,0x00,
13330x6,0x22,0x00,0x00,
13340x6,0x20,0x00,0x02,
13350x6,0x10,0x00,0x01,
13360x6,0x00,0x20,0x01,
13370x6,0x02,0x20,0x00,
13380x6,0x01,0x10,0x00,
13390x6,0x01,0x00,0x20,
13400x6,0x00,0x20,0x02,
13410x6,0x01,0x20,0x02,
13420x6,0x10,0x01,0x00,
13430x6,0x02,0x00,0x10,
13440x6,0x00,0x10,0x01,
13450x6,0x10,0x01,0x20,
13460x6,0x20,0x02,0x10,
13470x6,0x00,0x00,0x22,
13480x6,0x10,0x00,0x02,
13490x6,0x00,0x02,0x20,
13500x6,0x20,0x02,0x00,
13510x6,0x00,0x00,0x11,
13520x6,0x02,0x10,0x01,
13530x6,0x00,0x01,0x10,
13540x6,0x00,0x02,0x11,
13550x4,0x01,0x02,
13560x4,0x02,0x01,
13570x4,0x01,0x00,
13580x4,0x10,0x20,
13590x4,0x20,0x10,
13600x4,0x20,0x00,
13610x4,0x11,0x00,
13620x4,0x02,0x00,
13630x4,0x12,0x00,
13640x4,0x00,0x21,
13650x4,0x22,0x00,
13660x4,0x00,0x12,
13670x4,0x21,0x00,
13680x4,0x02,0x11,
13690x4,0x00,0x01,
13700x4,0x10,0x02,
13710x4,0x02,0x20,
13720x4,0x20,0x11,
13730x4,0x01,0x10,
13740x4,0x21,0x10,
13750x4,0x10,0x00,
13760x4,0x10,0x22,
13770x4,0x20,0x20,
13780x4,0x00,0x22,
13790x4,0x01,0x22,
13800x4,0x20,0x01,
13810x4,0x02,0x02,
13820x4,0x00,0x20,
13830x4,0x00,0x10,
13840x4,0x00,0x11,
13850x4,0x22,0x01,
13860x4,0x11,0x20,
13870x4,0x12,0x01,
13880x4,0x12,0x20,
13890x4,0x11,0x02,
13900x4,0x10,0x10,
13910x4,0x01,0x01,
13920x4,0x02,0x21,
13930x4,0x20,0x12,
13940x4,0x01,0x12,
13950x4,0x22,0x11,
13960x4,0x21,0x12,
13970x4,0x22,0x10,
13980x4,0x21,0x02,
13990x4,0x20,0x02,
14000x4,0x10,0x01,
14010x4,0x00,0x02,
14020x4,0x10,0x21,
14030x4,0x01,0x20,
14040x4,0x11,0x22,
14050x4,0x12,0x21,
14060x4,0x22,0x20,
14070x4,0x02,0x10,
14080x4,0x02,0x22,
14090x4,0x11,0x10,
14100x4,0x22,0x02,
14110x4,0x20,0x21,
14120x4,0x01,0x11,
14130x4,0x11,0x01,
14140x4,0x10,0x12,
14150x4,0x02,0x12,
14160x4,0x20,0x22,
14170x4,0x21,0x20,
14180x4,0x01,0x21,
14190x4,0x12,0x02,
14200x4,0x21,0x11,
14210x4,0x12,0x22,
14220x4,0x12,0x10,
14230x4,0x22,0x21,
14240x4,0x10,0x11,
14250x4,0x21,0x01,
14260x4,0x11,0x12,
14270x4,0x12,0x11,
14280x4,0x66,0x66,
14290x4,0x22,0x22,
14300x4,0x11,0x21,
14310x4,0x11,0x11,
14320x4,0x21,0x22,
14330x4,0x00,0x00,
14340x4,0x22,0x12,
14350x4,0x12,0x12,
14360x4,0x21,0x21,
14370x4,0x42,0x00,
14380x4,0x00,0x04,
14390x4,0x40,0x00,
14400x4,0x30,0x00,
14410x4,0x31,0x00,
14420x4,0x00,0x03,
14430x4,0x00,0x14,
14440x4,0x00,0x13,
14450x4,0x01,0x24,
14460x4,0x20,0x13,
14470x4,0x01,0x42,
14480x4,0x14,0x20,
14490x4,0x42,0x02,
14500x4,0x13,0x00,
14510x4,0x00,0x24,
14520x4,0x31,0x20,
14530x4,0x22,0x13,
14540x4,0x11,0x24,
14550x4,0x12,0x66,
14560x4,0x30,0x01,
14570x4,0x02,0x13,
14580x4,0x12,0x42,
14590x4,0x40,0x10,
14600x4,0x40,0x02,
14610x4,0x01,0x04,
14620x4,0x24,0x00,
14630x4,0x42,0x10,
14640x4,0x21,0x13,
14650x4,0x13,0x12,
14660x4,0x31,0x21,
14670x4,0x21,0x24,
14680x4,0x00,0x40,
14690x4,0x10,0x24,
14700x4,0x10,0x42,
14710x4,0x32,0x01,
14720x4,0x11,0x42,
14730x4,0x20,0x31,
14740x4,0x12,0x40,
14750x2,0x00,
14760x2,0x10,
14770x2,0x20,
14780x2,0x30,
14790x2,0x40,
14800x2,0x50,
14810x2,0x60,
14820x2,0x70,
14830x2,0x01,
14840x2,0x11,
14850x2,0x21,
14860x2,0x31,
14870x2,0x41,
14880x2,0x51,
14890x2,0x61,
14900x2,0x71,
14910x2,0x02,
14920x2,0x12,
14930x2,0x22,
14940x2,0x32,
14950x2,0x42,
14960x2,0x52,
14970x2,0x62,
14980x2,0x72,
14990x2,0x03,
15000x2,0x13,
15010x2,0x23,
15020x2,0x33,
15030x2,0x43,
15040x2,0x53,
15050x2,0x63,
15060x2,0x73,
15070x2,0x04,
15080x2,0x14,
15090x2,0x24,
15100x2,0x34,
15110x2,0x44,
15120x2,0x54,
15130x2,0x64,
15140x2,0x74,
15150x2,0x05,
15160x2,0x15,
15170x2,0x25,
15180x2,0x35,
15190x2,0x45,
15200x2,0x55,
15210x2,0x65,
15220x2,0x75,
15230x2,0x06,
15240x2,0x16,
15250x2,0x26,
15260x2,0x36,
15270x2,0x46,
15280x2,0x56,
15290x2,0x66,
15300x2,0x76,
15310x2,0x07,
15320x2,0x17,
15330x2,0x27,
15340x2,0x37,
15350x2,0x47,
15360x2,0x57,
15370x2,0x67,
15380x2,0x77
1539];
1540
1541const DUCK_VECTABLES: [&[u8]; 3] = [ DUCK_VECTBL2, DUCK_VECTBL3, DUCK_VECTBL4 ];