]> git.nihav.org Git - nihav.git/blame - nihav-game/src/codecs/smush/v1.rs
fix clippy warnings
[nihav.git] / nihav-game / src / codecs / smush / v1.rs
CommitLineData
c17769db
KS
1use nihav_core::codecs::*;
2use nihav_core::io::byteio::*;
3
4struct Glyphs {
5 data: [[[u8; 16]; 256]; 2],
6 glyph8: [[u8; 64]; 256],
7 glyph8_init: bool,
8}
9
10impl Glyphs {
11 fn new() -> Self {
12 Self {
13 data: [[[0; 16]; 256]; 2],
14 glyph8: [[0; 64]; 256],
15 glyph8_init: false,
16 }
17 }
18 fn make_glyphs_4(&mut self, mode: u8) {
19 for i in (1..16).step_by(2) {
20 let cy = (i as u8) + mode;
21 for j in 0..16 {
22 let dst = &mut self.data[0][(i / 2) * 16 + j];
23
24 let cx = (j as u8) + mode;
25 let avg = mode + (((i + j) >> 1) as u8);
26 if avg == cx || avg == cy {
27 dst[ 0] = cx; dst[ 1] = cy; dst[ 2] = cx; dst[ 3] = cy;
28 dst[ 4] = cy; dst[ 5] = cx; dst[ 6] = cy; dst[ 7] = cy;
29 dst[ 8] = cx; dst[ 9] = cy; dst[10] = cx; dst[11] = cy;
30 dst[12] = cx; dst[13] = cx; dst[14] = cy; dst[15] = cx;
31 } else {
32 let c0 = avg;
33 let c1 = ((u16::from(avg) + u16::from(cy)) >> 1) as u8;
34 let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8;
35 dst[ 0] = c0; dst[ 1] = c0; dst[ 2] = c1; dst[ 3] = cy;
36 dst[ 4] = c0; dst[ 5] = c0; dst[ 6] = c1; dst[ 7] = cy;
37 dst[ 8] = c2; dst[ 9] = c2; dst[10] = c0; dst[11] = c1;
38 dst[12] = cx; dst[13] = cx; dst[14] = c2; dst[15] = c0;
39 }
40 }
41 }
42 for i in (0..16).step_by(2) {
43 let cy = (i as u8) + mode;
44 for j in 0..16 {
45 let dst = &mut self.data[0][128 + (i / 2) * 16 + j];
46
47 let cx = (j as u8) + mode;
48 let avg = mode + (((i + j) >> 1) as u8);
49 if avg == cx || avg == cy {
50 dst[ 0] = cy; dst[ 1] = cy; dst[ 2] = cx; dst[ 3] = cy;
51 dst[ 4] = cy; dst[ 5] = cy; dst[ 6] = cy; dst[ 7] = cx;
52 dst[ 8] = cx; dst[ 9] = cy; dst[10] = cx; dst[11] = cx;
53 dst[12] = cy; dst[13] = cx; dst[14] = cy; dst[15] = cx;
54 } else {
55 let c1 = ((u16::from(avg) + u16::from(cy)) >> 1) as u8;
56 let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8;
57 dst[ 0] = cy; dst[ 1] = cy; dst[ 2] = c1; dst[ 3] = cx;
58 dst[ 4] = cy; dst[ 5] = cy; dst[ 6] = c1; dst[ 7] = cx;
59 dst[ 8] = c1; dst[ 9] = c1; dst[10] = cx; dst[11] = c2;
60 dst[12] = cx; dst[13] = cx; dst[14] = c2; dst[15] = cx;
61 }
62 }
63 }
64 }
65 fn make_glyphs_5(&mut self, mode: u8) {
66 for i in 0..8 {
67 let cy = (i as u8) + mode;
68 for j in 0..8 {
69 let dst = &mut self.data[0][i * 8 + j];
70
71 let cx = (j as u8) + mode;
72 let avg = mode + (((i + j) >> 1) as u8);
73 let c0 = avg;
74 let c1 = ((u16::from(avg) + u16::from(cy)) >> 1) as u8;
75 let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8;
76
77 dst[ 0] = c0; dst[ 1] = c0; dst[ 2] = c1; dst[ 3] = cy;
78 dst[ 4] = c0; dst[ 5] = c0; dst[ 6] = c1; dst[ 7] = cy;
79 dst[ 8] = c2; dst[ 9] = c2; dst[10] = c0; dst[11] = c1;
80 dst[12] = cx; dst[13] = cx; dst[14] = c2; dst[15] = c0;
81 }
82 }
83 for i in 0..8 {
84 let cy = (i as u8) + mode;
85 for j in 0..8 {
86 let dst = &mut self.data[0][i * 8 + j + 64];
87
88 let cx = (j as u8) + mode;
89 let avg = mode + (((i + j) >> 1) as u8);
90 let c0 = avg;
91 let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8;
92
93 dst[ 0] = cy; dst[ 1] = cy; dst[ 2] = cy; dst[ 3] = cy;
94 dst[ 4] = c0; dst[ 5] = c0; dst[ 6] = c0; dst[ 7] = c0;
95 dst[ 8] = c2; dst[ 9] = c2; dst[10] = c2; dst[11] = c2;
96 dst[12] = cx; dst[13] = cx; dst[14] = cx; dst[15] = cx;
97 }
98 }
99 for i in 0..8 {
100 let cy = (i as u8) + mode;
101 for j in 0..8 {
102 let dst = &mut self.data[0][i * 8 + j + 128];
103
104 let cx = (j as u8) + mode;
105 let avg = mode + (((i + j) >> 1) as u8);
106 let c0 = avg;
107 let c1 = ((u16::from(avg) + u16::from(cy)) >> 1) as u8;
108 let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8;
109
110 dst[ 0] = cy; dst[ 1] = cy; dst[ 2] = c1; dst[ 3] = c0;
111 dst[ 4] = cy; dst[ 5] = cy; dst[ 6] = c1; dst[ 7] = c0;
112 dst[ 8] = c1; dst[ 9] = c1; dst[10] = c0; dst[11] = c2;
113 dst[12] = c0; dst[13] = c0; dst[14] = c2; dst[15] = cx;
114 }
115 }
116 for i in 0..8 {
117 let cy = (i as u8) + mode;
118 for j in 0..8 {
119 let dst = &mut self.data[0][i * 8 + j + 192];
120
121 let cx = (j as u8) + mode;
122 let avg = mode + (((i + j) >> 1) as u8);
123 let c0 = avg;
124 let c2 = ((u16::from(avg) + u16::from(cx)) >> 1) as u8;
125
126 dst[ 0] = cy; dst[ 1] = c0; dst[ 2] = c2; dst[ 3] = cx;
127 dst[ 4] = cy; dst[ 5] = c0; dst[ 6] = c2; dst[ 7] = cx;
128 dst[ 8] = cy; dst[ 9] = c0; dst[10] = c2; dst[11] = cx;
129 dst[12] = cy; dst[13] = c0; dst[14] = c2; dst[15] = cx;
130 }
131 }
132 }
133 fn read_additional(&mut self, br: &mut ByteReader, add: u16) -> DecoderResult<()> {
134 if add > 0 {
135 validate!(add <= 256);
136 let mut gbuf = [0; 8];
137 for glyph in self.data[1].iter_mut().take(add as usize) {
138 br.read_buf(&mut gbuf)?;
139 for (pair, &b) in glyph.chunks_mut(2).zip(gbuf.iter()) {
140 pair[0] = b >> 4;
141 pair[1] = b & 0xF;
142 }
143 }
144 }
145 Ok(())
146 }
147 fn make_glyphs_47(&mut self) {
148 super::make_glyphs_47(&mut self.data[0], &mut self.glyph8);
149 self.glyph8_init = true;
150 }
151}
152
153struct FrameData {
154 info: NACodecInfoRef,
155 pal: [u8; 768],
156 fpal: [u16; 768],
157 pdelta: [u16; 768],
158 width: usize,
159 height: usize,
160 frm0: Vec<u8>,
161 frm1: Vec<u8>,
162 frm2: Vec<u8>,
163}
164
165impl FrameData {
166 fn new() -> Self {
167 Self {
168 info: NACodecInfoRef::default(),
169 pal: [0; 768],
170 fpal: [0; 768],
171 pdelta: [0; 768],
172 width: 0,
173 height: 0,
174 frm0: Vec::new(),
175 frm1: Vec::new(),
176 frm2: Vec::new(),
177 }
178 }
179 fn init(&mut self, info: NACodecInfoRef) -> DecoderResult<()> {
180 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
181 self.width = vinfo.get_width();
182 self.height = vinfo.get_height();
183self.width = (self.width + 7) & !7;
184self.height = (self.height + 7) & !7;
185 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT));
186 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
187 if let Some(edata) = info.get_extradata() {
188 validate!(edata.len() > 768);
189 self.pal.copy_from_slice(&edata[1..][..768]);
190 }
191
192 self.frm0.resize(self.width * self.height, 0);
193 self.frm1.resize(self.width * self.height, 0);
194 self.frm2.resize(self.width * self.height, 0);
195 Ok(())
196 } else {
197 Err(DecoderError::InvalidData)
198 }
199 }
200 #[inline]
201 fn set_pixel(&mut self, xoff: i16, yoff: i16, x: usize, y: usize, pix: u8) {
202 let xpos = (xoff as isize) + (x as isize);
203 if xpos < 0 { return; }
204 let xpos = xpos as usize;
205 let ypos = (yoff as isize) + (y as isize);
206 if ypos < 0 { return; }
207 let ypos = ypos as usize;
208 if xpos < self.width && ypos < self.height {
209 self.frm0[xpos + ypos * self.width] = pix;
210 }
211 }
212 fn get_pixel(&mut self, xoff: i16, yoff: i16, x: usize, y: usize) -> u8 {
213 let xpos = (xoff as isize) + (x as isize);
214 if xpos < 0 { return 0; }
215 let xpos = xpos as usize;
216 let ypos = (yoff as isize) + (y as isize);
217 if ypos < 0 { return 0; }
218 let ypos = ypos as usize;
219 if xpos < self.width && ypos < self.height {
220 self.frm0[xpos + ypos * self.width]
221 } else {
222 0
223 }
224 }
225 fn loop_filter(&mut self, _xoff: i16, _yoff: i16, _x: usize, _y: usize) {
226/* let xpos = (xoff as isize) + (x as isize);
227 if xpos < 0 { return; }
228 let xpos = xpos as usize;
229 let ypos = (yoff as isize) + (y as isize);
230 if ypos < 0 { return; }
231 let ypos = ypos as usize;
232 if xpos < self.width && ypos < self.height {
233 let start = xpos + ypos * self.width;
234 if xpos > 0 {
235 for row in self.frm0[start - 1..].chunks_mut(self.width).take(4) {
236 let x0 = row[0];
237 let x1 = row[1];
238 row[1] = 0x80 | (x0.wrapping_add(x1) >> 1);
239 }
240 }
241 if ypos > 0 {
242 for i in 0..4 {
243 let y0 = self.frm0[start + i];
244 let y1 = &mut self.frm0[start + i + self.width];
245 *y1 = 0x80 | (y1.wrapping_add(y0) >> 1);
246 }
247 }
248 }*/
249 }
250 fn get_frame(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
251 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?;
252 if let Some(ref mut vbuf) = bufinfo.get_vbuf() {
253 let stride = vbuf.get_stride(0);
254 let paloff = vbuf.get_offset(1);
255 let data = vbuf.get_data_mut().unwrap();
256 for (dst, src) in data.chunks_mut(stride).zip(self.frm0.chunks(self.width).take(self.height)) {
257 dst[..self.width].copy_from_slice(src);
258 }
259 data[paloff..][..768].copy_from_slice(&self.pal);
260 } else {
261 return Err(DecoderError::Bug);
262 }
263
264 let is_intra = pkt.keyframe;
265 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
266 frm.set_keyframe(is_intra);
267 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
268 Ok(frm.into_ref())
269 }
270}
271
272fn do_mc(dst: &mut [u8], src: &[u8], stride: usize, xoff: isize, yoff: isize, w: usize, h: usize) {
273 let mut pos = xoff + yoff * (stride as isize);
274 for row in dst.chunks_mut(stride).take(4) {
275 for i in 0..4 {
276 row[i] = if pos >= 0 && (pos as usize) < w + (h - 1) * stride {
277 src[pos as usize]
278 } else { 0 };
279 pos += 1;
280 }
281 pos -= 4;
282 pos += stride as isize;
283 }
284}
285
286#[allow(clippy::too_many_arguments)]
287fn do_block47(br: &mut ByteReader, dst: &mut [u8], frm1: &[u8], frm2: &[u8], x: usize, y: usize, stride: usize, bsize: usize, clr: &[u8; 6], glyphs: &Glyphs) -> DecoderResult<()> {
288 let op = br.read_byte()?;
289 match op {
290 0xFF if bsize > 2 => {
291 let hsize = bsize / 2;
292 do_block47(br, dst, frm1, frm2, x, y, stride, hsize, clr, glyphs)?;
293 do_block47(br, &mut dst[hsize..], frm1, frm2, x + hsize, y, stride, bsize / 2, clr, glyphs)?;
294 do_block47(br, &mut dst[hsize * stride..], frm1, frm2, x, y + hsize, stride, hsize, clr, glyphs)?;
295 do_block47(br, &mut dst[hsize * (stride + 1)..], frm1, frm2, x + hsize, y + hsize, stride, bsize / 2, clr, glyphs)?;
296 },
297 0xFF => {
298 br.read_buf(&mut dst[..2])?;
299 br.read_buf(&mut dst[stride..][..2])?;
300 },
301 0xFE => {
302 let pix = br.read_byte()?;
303 for dst in dst.chunks_mut(stride).take(bsize) {
304 for el in dst[..bsize].iter_mut() {
305 *el = pix;
306 }
307 }
308 },
309 0xFD => {
310 let idx = br.read_byte()? as usize;
311 let mut clr = [0; 2];
312 clr[1] = br.read_byte()?;
313 clr[0] = br.read_byte()?;
314 let mut glyph = if bsize == 8 { glyphs.glyph8[idx].iter() } else { glyphs.data[0][idx].iter() };
315
316 for dst in dst.chunks_mut(stride).take(bsize) {
317 for el in dst[..bsize].iter_mut() {
318 *el = clr[*glyph.next().unwrap_or(&0) as usize];
319 }
320 }
321 },
322 0xFC => {
323 let off = x + y * stride;
324 let src = &frm1[off..];
325 for (dst, src) in dst.chunks_mut(stride).zip(src.chunks(stride)).take(bsize) {
326 dst[..bsize].copy_from_slice(&src[..bsize]);
327 }
328 },
329 0xF8..=0xFB => {
330 let pix = clr[(op & 7) as usize];
331 for dst in dst.chunks_mut(stride).take(bsize) {
332 for el in dst[..bsize].iter_mut() {
333 *el = pix;
334 }
335 }
336 },
337 _ => {
338 let mx = C47_MV[0][op as usize][0] as isize;
339 let my = C47_MV[0][op as usize][1] as isize;
340 let off = (x as isize) + mx + ((y as isize) + my) * (stride as isize);
341 validate!(off >= 0);
342 let src = &frm2[off as usize..];
343 for (dst, src) in dst.chunks_mut(stride).zip(src.chunks(stride)).take(bsize) {
344 dst[..bsize].copy_from_slice(&src[..bsize]);
345 }
346 },
347 };
348 Ok(())
349}
350
351macro_rules! c48_mv {
352 (index; $dst: expr, $src: expr, $br: expr, $x: expr, $y: expr, $stride: expr, $size: expr, $mvsel: expr) => ({
353 for yy in (0..8).step_by($size) {
354 for xx in (0..8).step_by($size) {
355 let idx = $br.read_byte()? as usize;
356 validate!(idx < 255);
357 let mx = C47_MV[$mvsel][idx][0] as isize;
358 let my = C47_MV[$mvsel][idx][1] as isize;
359 c48_mv!(common; &mut $dst[xx + yy * $stride..], $src, $x + xx, $y + yy, mx, my, $stride, $size)
360 }
361 }
362
363 });
364 (offset; $dst: expr, $src: expr, $br: expr, $x: expr, $y: expr, $w: expr, $stride: expr, $size: expr) => ({
365 for yy in (0..8).step_by($size) {
366 for xx in (0..8).step_by($size) {
367 let offset = $br.read_u16le()? as i16 as isize;
368 let mx = offset % ($w as isize);
369 let my = offset / ($w as isize);
370 c48_mv!(common; &mut $dst[xx + yy * $stride..], $src, $x + xx, $y + yy, mx, my, $stride, $size)
371 }
372 }
373 });
374 (common; $dst: expr, $src: expr, $x: expr, $y: expr, $mx: expr, $my: expr, $stride: expr, $size: expr) => {{
375 let srcpos = ($x as isize) + $mx + (($y as isize) + $my) * ($stride as isize);
376 validate!(srcpos >= 0);
377 for (dst, src) in $dst.chunks_mut($stride).zip($src[srcpos as usize..].chunks($stride)).take($size) {
378 let size = dst.len().min(src.len()).min($size);
379 dst[..size].copy_from_slice(&src[..size]);
380 }
381 }}
382}
383
384fn scale2x(block: &[u8; 16], dst: &mut [u8], stride: usize) {
385 for (drow, src) in dst.chunks_mut(stride * 2).zip(block.chunks_exact(4)) {
386 for row in drow.chunks_mut(stride) {
387 for (dpair, &el) in row.chunks_exact_mut(2).zip(src.iter()) {
388 dpair[0] = el;
389 dpair[1] = el;
390 }
391 }
392 }
393}
394
395struct Smush1Decoder {
396 glyphs: Glyphs,
397 pic: FrameData,
398 version: u8,
399 prev_seq: u16,
400 reorder: u8,
401 filter: [[u8; 256]; 256],
402}
403
404impl Smush1Decoder {
405 fn new() -> Self {
406 Self {
407 glyphs: Glyphs::new(),
408 pic: FrameData::new(),
409 version: 0,
410 prev_seq: 0,
411 reorder: 0,
412 filter: [[0; 256]; 256],
413 }
414 }
415
416 fn decode_rle(br: &mut ByteReader, dst: &mut [u8], w: usize, h: usize, stride: usize) -> DecoderResult<()> {
417 let mut x = 0;
418 let mut y = 0;
419 let mut len = 0;
420 let mut clr = 0;
421 let mut run = false;
422 while (x != 0) || (y != h) {
423 if len == 0 {
424 let op = br.read_byte()?;
425 run = (op & 1) != 0;
426 if run {
427 clr = br.read_byte()?;
428 }
429 len = ((op >> 1) + 1) as usize;
430 }
431 if run {
432 dst[x + y * stride] = clr;
433 } else {
434 dst[x + y * stride] = br.read_byte()?;
435 }
436 len -= 1;
437 x += 1;
438 if x == w {
439 x = 0;
440 y += 1;
441 }
442 }
443 validate!(len == 0);
444
445 Ok(())
446 }
447
448 fn decode_1(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, transparent: bool) -> DecoderResult<()> {
449 for yy in 0..h {
450 let len = u64::from(br.read_u16le()?);
451 let end = br.tell() + len;
452 let mut xx = 0;
453 while (br.tell() < end) && (xx < w) {
454 let op = br.read_byte()?;
455 let len = ((op >> 1) + 1) as usize;
456 if (op & 1) == 0 {
457 for _ in 0..len {
458 let clr = br.read_byte()?;
459 if !transparent || clr != 0 {
460 self.pic.set_pixel(x, y, xx, yy, clr);
461 }
462 xx += 1;
463 }
464 } else {
465 let clr = br.read_byte()?;
466 if !transparent || clr != 0 {
467 for _ in 0..len {
468 self.pic.set_pixel(x, y, xx, yy, clr);
469 xx += 1;
470 }
471 } else {
472 xx += len;
473 }
474 }
475 }
476 validate!(br.tell() == end && xx == w);
477 }
478
479 Ok(())
480 }
481 #[allow(clippy::verbose_bit_mask)]
482 fn decode_2(&mut self, br: &mut ByteReader, x: i16, y: i16, _w: usize, _h: usize, len: usize) -> DecoderResult<()> {
483
484 validate!((len & 3) == 0);
485 let mut xpos = x;
486 let mut ypos = y;
487 for _ in 0..len/4 {
488 let xoff = br.read_u16le()? as i16;
489 let yoff = i16::from(br.read_byte()?);
490 let pix = br.read_byte()?;
491
492 xpos += xoff;
493 ypos += yoff;
494 self.pic.set_pixel(xpos, ypos, 0, 0, pix);
495 }
496 Ok(())
497 }
498 #[allow(clippy::too_many_arguments)]
499 fn decode_4(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, mode: u8, add: u16) -> DecoderResult<()> {
500 self.glyphs.make_glyphs_4(mode);
501 self.glyphs.read_additional(br, add)?;
502
503 for col in (0..w).step_by(4) {
504 let mut mask = 0;
505 let mut bits = 0;
506 for row in (0..h).step_by(4) {
507 let bit = if add > 0 {
508 if bits == 0 {
509 mask = br.read_byte()?;
510 bits = 8;
511 }
512 let bit = (mask & 0x80) != 0;
513 mask <<= 1;
514 bits -= 1;
515 bit
516 } else {
517 false
518 };
519
520 let tile_no = br.read_byte()? as usize;
521 if !bit && (tile_no == 0x80) {
522 continue;
523 }
524 let src = &self.glyphs.data[bit as usize][tile_no];
525 for (y1, srow) in src.chunks(4).enumerate() {
526 for (x1, &pix) in srow.iter().enumerate() {
527 self.pic.set_pixel(x, y, col + x1, row + y1, pix);
528 }
529 }
530 if !bit {
531 self.pic.loop_filter(x, y, col, row);
532 }
533 }
534 }
535
536 Ok(())
537 }
538 #[allow(clippy::too_many_arguments)]
539 fn decode_5(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, mode: u8, add: u16) -> DecoderResult<()> {
540 self.glyphs.make_glyphs_5(mode);
541 self.glyphs.read_additional(br, add)?;
542
543 for col in (0..w).step_by(4) {
544 let mut mask = 0;
545 let mut bits = 0;
546 for row in (0..h).step_by(4) {
547 let bit = if add > 0 {
548 if bits == 0 {
549 mask = br.read_byte()?;
550 bits = 8;
551 }
552 let bit = (mask & 0x80) != 0;
553 mask <<= 1;
554 bits -= 1;
555 bit
556 } else {
557 false
558 };
559
560 let tile_no = br.read_byte()? as usize;
561 let src = &self.glyphs.data[bit as usize][tile_no];
562 for (y1, srow) in src.chunks(4).enumerate() {
563 for (x1, &pix) in srow.iter().enumerate() {
564 self.pic.set_pixel(x, y, col + x1, row + y1, pix);
565 }
566 }
567 if !bit {
568 self.pic.loop_filter(x, y, col, row);
569 }
570 }
571 }
572
573 Ok(())
574 }
575 fn decode_21(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, size: usize) -> DecoderResult<()> {
576 let end = br.tell() + (size as u64);
577 for yy in 0..h {
578 if br.tell() >= end { break; }
579 let len = u64::from(br.read_u16le()?);
580 let end = br.tell() + len;
581 let mut xx = 0;
582 let mut skip = true;
583 while (br.tell() < end) && (xx <= w) {
584 let len = br.read_u16le()? as usize;
585 if !skip {
586 for _ in 0..=len {
587 let pix = br.read_byte()?;
588 self.pic.set_pixel(x, y, xx, yy, pix);
589 xx += 1;
590 }
591 } else {
592 for _ in 0..len {
593 self.pic.set_pixel(x, y, xx, yy, 0);
594 xx += 1;
595 }
596 }
597 skip = !skip;
598 }
599 validate!(br.tell() == end && xx == w + 1);
600 }
601
602 Ok(())
603 }
604 #[allow(clippy::too_many_arguments)]
605 fn decode_23(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, bias: u8, add: u16, old: bool) -> DecoderResult<()> {
606 let mut lut = [0; 256];
607 if old {
608 for (i, el) in lut.iter_mut().enumerate() {
609 *el = (i as u8).wrapping_add(bias.wrapping_sub(0x30));
610 }
611 } else if add != 256 {
612 for (i, el) in lut.iter_mut().enumerate() {
613 *el = (i as u8).wrapping_add(add as u8);
614 }
615 } else {
616 br.read_buf(&mut lut)?;
617 }
618 for yy in 0..h {
619 let len = u64::from(br.read_u16le()?);
620 let end = br.tell() + len;
621 let mut xx = 0;
622 let mut skip = true;
623 while (br.tell() < end) && (xx <= w) {
624 let len = br.read_byte()? as usize;
625 if !skip {
626 for _ in 0..len {
627 let pix = self.pic.get_pixel(x, y, xx, yy);
628 self.pic.set_pixel(x, y, xx, yy, lut[pix as usize]);
629 xx += 1;
630 }
631 } else {
632 xx += len;
633 }
634 skip = !skip;
635 }
636 validate!(br.tell() == end && xx == w + 1);
637 }
638
639 Ok(())
640 }
641 fn decode_37(&mut self, br: &mut ByteReader, x: i16, y: i16, mut w: usize, mut h: usize) -> DecoderResult<()> {
642 let compr = br.read_byte()?;
643 let mv_off = br.read_byte()? as usize;
644 validate!(mv_off <= 2);
645 let seq = br.read_u16le()?;
646 let _unp_size = br.read_u32le()?;
647 let _packed_size = br.read_u32le()?;
648 let flags = br.read_byte()?;
649 br.read_skip(3)?;
650
651 w = (w + 3) & !3;
652 h = (h + 3) & !3;
653
654 validate!(x >= 0 && y >= 0);
655 let x = x as usize;
656 let y = y as usize;
657 validate!((x + w <= self.pic.width) && (y + h <= self.pic.height));
658
659 if compr == 0 || compr == 2 {
660 for el in self.pic.frm1.iter_mut() {
661 *el = 0;
662 }
663 for el in self.pic.frm2.iter_mut() {
664 *el = 0;
665 }
666 } else if ((seq & 1) != 0) || ((flags & 1) == 0) {
667 std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2);
668 }
669
670 let stride = self.pic.width;
671 let dst = &mut self.pic.frm0[x + y * stride..];
672 let prv = &self.pic.frm2[x + y * stride..];
673 match compr {
674 0 => {
675 for line in dst.chunks_mut(stride).take(h) {
676 br.read_buf(&mut line[..w])?;
677 }
678 },
679 1 => {
680 let mut len = -1;
681 let mut run = false;
682 let mut code = 0;
683 for (row_no, row) in dst.chunks_mut(stride * 4).take(h / 4).enumerate() {
684 for col in (0..w).step_by(4) {
685 let skip_code = if len < 0 {
686 let op = br.read_byte()?;
687 len = (op >> 1) as i8;
688 run = (op & 1) != 0;
689 false
690 } else {
691 run
692 };
693 if !skip_code {
694 code = br.read_byte()?;
695 if code == 0xFF {
696 len -= 1;
697 for drow in row[col..].chunks_mut(stride) {
698 for el in drow[..4].iter_mut() {
699 if len < 0 {
700 let op = br.read_byte()?;
701 len = (op >> 1) as i8;
702 run = (op & 1) != 0;
703 if run {
704 code = br.read_byte()?;
705 }
706 }
707 if run {
708 *el = code;
709 } else {
710 *el = br.read_byte()?;
711 }
712 len -= 1;
713 }
714 }
715 continue;
716 }
717 }
718 let idx = code as usize;
719 let mx = C37_MV[mv_off][idx * 2] as isize;
720 let my = C37_MV[mv_off][idx * 2 + 1] as isize;
721 do_mc(&mut row[col..], &self.pic.frm2, stride,
722 (x as isize) + (col as isize) + mx,
723 (y as isize) + (row_no as isize) * 4 + my,
724 self.pic.width, self.pic.height);
725 len -= 1;
726 }
727 }
728 },
729 2 => {
730 Self::decode_rle(br, dst, w, h, stride)?;
731 },
732 3 | 4 => {
733 let has_fills = (flags & 4) != 0;
734 let has_skips = compr == 4;
735 let mut skip_run = 0;
736 for (row_no, row) in dst.chunks_mut(stride * 4).take(h / 4).enumerate() {
737 for col in (0..w).step_by(4) {
738 if skip_run > 0 {
739 for (drow, srow) in row[col..].chunks_mut(stride).zip(prv[col + row_no * 4 * stride..].chunks(stride)) {
740 drow[..4].copy_from_slice(&srow[..4]);
741 }
742 skip_run -= 1;
743 continue;
744 }
745 let opcode = br.read_byte()?;
746 match opcode {
747 0xFF => {
748 for drow in row[col..].chunks_mut(stride) {
749 br.read_buf(&mut drow[..4])?;
750 }
751 },
752 0xFE if has_fills => {
753 for drow in row[col..].chunks_mut(stride) {
754 let clr = br.read_byte()?;
755 for el in drow[..4].iter_mut() {
756 *el = clr;
757 }
758 }
759 },
760 0xFD if has_fills => {
761 let clr = br.read_byte()?;
762 for drow in row[col..].chunks_mut(stride) {
763 for el in drow[..4].iter_mut() {
764 *el = clr;
765 }
766 }
767 },
768 0 if has_skips => {
769 skip_run = br.read_byte()?;
770 for (drow, srow) in row[col..].chunks_mut(stride).zip(prv[col + row_no * 4 * stride..].chunks(stride)) {
771 drow[..4].copy_from_slice(&srow[..4]);
772 }
773 },
774 _ => {
775 let idx = opcode as usize;
776 let mx = C37_MV[mv_off][idx * 2] as isize;
777 let my = C37_MV[mv_off][idx * 2 + 1] as isize;
778 do_mc(&mut row[col..], &self.pic.frm2, stride,
779 (x as isize) + (col as isize) + mx,
780 (y as isize) + (row_no as isize) * 4 + my,
781 self.pic.width, self.pic.height);
782 },
783 };
784 }
785 }
786 },
787 _ => return Err(DecoderError::InvalidData),
788 };
789
790 Ok(())
791 }
792 fn decode_47(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize) -> DecoderResult<()> {
793 let seq = br.read_u16le()?;
794 let compr = br.read_byte()?;
795 let reorder = br.read_byte()?;
796 let flags = br.read_byte()?;
797 br.read_skip(3)?;
798 let mut clr = [0; 6];
799 br.read_buf(&mut clr)?;
800 let _dec_size = br.read_u32le()?;
801 br.read_skip(4)?;
802 br.read_skip(4)?;
803
804 if (flags & 1) != 0 {
805 for i in 0..256 {
806 for j in i..256 {
807 let val = br.read_byte()?;
808 self.filter[i][j] = val;
809 self.filter[j][i] = val;
810 }
811 }
812 }
813
814 if compr == 2 && !self.glyphs.glyph8_init {
815 self.glyphs.make_glyphs_47();
816 }
817
818 if seq == 0 {
819 for el in self.pic.frm1.iter_mut() {
820 *el = 0;
821 }
822 for el in self.pic.frm2.iter_mut() {
823 *el = 0;
824 }
825 }
826
827 validate!(x >= 0 && y >= 0);
828 let x = x as usize;
829 let y = y as usize;
830 validate!((x + w <= self.pic.width) && (y + h <= self.pic.height));
831
832 let stride = self.pic.width;
833 let dst = &mut self.pic.frm0[x + y * stride..];
834 match compr {
835 0 => {
836 for line in dst.chunks_mut(stride).take(h) {
837 br.read_buf(&mut line[..w])?;
838 }
839 },
840 1 => {
841 for row in dst.chunks_mut(stride * 2).take((h + 1) / 2) {
842 for col in (0..w).step_by(2) {
843 let pix = br.read_byte()?;
844 row[col] = pix;
845 row[col + 1] = pix;
846 row[col + stride] = pix;
847 row[col + stride + 1] = pix;
848 }
849 }
850 },
851 2 => {
852 for (row_no, row) in dst.chunks_mut(stride * 8).take((h + 7) / 8).enumerate() {
853 for col in (0..w).step_by(8) {
854 do_block47(br, &mut row[col..], &self.pic.frm1, &self.pic.frm2, col, row_no * 8, stride, 8, &clr, &self.glyphs)?;
855 }
856 }
857 },
858 3 => {
859 self.pic.frm0.copy_from_slice(&self.pic.frm2);
860 },
861 4 => {
862 self.pic.frm0.copy_from_slice(&self.pic.frm1);
863 },
864 5 => {
865 Self::decode_rle(br, dst, w, h, stride)?;
866 },
867 _ => return Err(DecoderError::InvalidData),
868 };
869
870 self.reorder = if seq == 0 || seq == self.prev_seq + 1 { reorder } else { 0 };
871 self.prev_seq = seq;
872
873 Ok(())
874 }
875 fn decode_48(&mut self, br: &mut ByteReader, x: i16, y: i16, mut w: usize, mut h: usize) -> DecoderResult<()> {
876 let compr = br.read_byte()?;
877 let mvsel = br.read_byte()? as usize;
878 validate!(mvsel < 2);
879 let _seq = br.read_u16le()?;
880 let _packed_size = br.read_u32le()?;
881 let _unpacked_size = br.read_u32le()?;
882 let flags = br.read_byte()?;
883 br.read_skip(3)?;
884 if (flags & 8) != 0 {
885 for i in 0..256 {
886 for j in i..256 {
887 let val = br.read_byte()?;
888 self.filter[i][j] = val;
889 self.filter[j][i] = val;
890 }
891 }
892 }
893
894 w = (w + 7) & !7;
895 h = (h + 7) & !7;
896 std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2);
897
898 validate!(x >= 0 && y >= 0);
899 let x = x as usize;
900 let y = y as usize;
901 validate!((x + w <= self.pic.width) && (y + h <= self.pic.height));
902
903 let stride = self.pic.width;
904 let dst = &mut self.pic.frm0[x + y * stride..];
905 match compr {
906 0 => {
907 for line in dst.chunks_mut(stride).take(h) {
908 br.read_buf(&mut line[..w])?;
909 }
910 },
911 2 => {
912 Self::decode_rle(br, dst, w, h, stride)?;
913 },
914 3 => {
915 let mut block = [0; 16];
916 for (row_no, row) in dst.chunks_mut(stride * 8).take((h + 7) / 8).enumerate() {
917 for col in (0..w).step_by(8) {
918 let op = br.read_byte()?;
919 match op {
920 0xFF => {
921 let val = br.read_byte()?;
922
923 // it should be interpolated which means reading top pixels...
924 for el in block.iter_mut() {
925 *el = val;
926 }
927 scale2x(&block, &mut row[col..], stride);
928 },
929 0xFE => {
930 c48_mv!(offset; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, w, stride, 8);
931 },
932 0xFD => {
933 block[ 5] = br.read_byte()?;
934 block[ 7] = br.read_byte()?;
935 block[13] = br.read_byte()?;
936 block[15] = br.read_byte()?;
937
938 // it should be interpolated which means reading top pixels...
939 block[ 0] = block[ 5];
940 block[ 1] = block[ 5];
941 block[ 4] = block[ 5];
942 block[ 2] = block[ 7];
943 block[ 3] = block[ 7];
944 block[ 6] = block[ 7];
945 block[ 8] = block[13];
946 block[ 9] = block[13];
947 block[12] = block[13];
948 block[10] = block[15];
949 block[11] = block[15];
950 block[14] = block[15];
951 scale2x(&block, &mut row[col..], stride);
952 },
953 0xFC => {
954 c48_mv!(index; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, stride, 4, mvsel);
955 },
956 0xFB => {
957 c48_mv!(offset; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, w, stride, 4);
958 },
959 0xFA => {
960 br.read_buf(&mut block)?;
961 scale2x(&block, &mut row[col..], stride);
962 },
963 0xF9 => {
964 c48_mv!(index; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, stride, 2, mvsel);
965 },
966 0xF8 => {
967 c48_mv!(offset; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, w, stride, 2);
968 },
969 0xF7 => {
970 for line in row[col..].chunks_mut(stride) {
971 br.read_buf(&mut line[..8])?;
972 }
973 },
974 _ => {
975 br.seek(SeekFrom::Current(-1))?;
976 c48_mv!(index; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, stride, 8, mvsel);
977 },
978 };
979 }
980 }
981 },
982 5 => {
983 for row in dst.chunks_mut(stride * 2).take((h + 1) / 2) {
984 let mut last = br.read_byte()?;
985 row[0] = last;
986 for col in (1..w).step_by(2) {
987 let new = br.read_byte()?;
988 row[col] = self.filter[last as usize][new as usize];
989 row[col + 1] = new;
990 last = new;
991 }
992 }
993 let mut off0 = 0;
994 let mut off1 = stride;
995 let mut off2 = stride * 2;
996 for _ in (1..h).step_by(2) {
997 for i in 0..w {
998 dst[off1 + i] = self.filter[dst[off0 + i] as usize][dst[off2 + i] as usize];
999 }
1000 off0 = off2;
1001 off1 += stride * 2;
1002 off2 += stride * 2;
1003 }
1004 },
1005 _ => return Err(DecoderError::InvalidData),
1006 };
1007 Ok(())
1008 }
1009}
1010
1011impl NADecoder for Smush1Decoder {
1012 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
1013 if let Some(edata) = info.get_extradata() {
1014 validate!(!edata.is_empty() && edata[0] <= 2);
1015 self.version = edata[0];
1016 }
1017 self.pic.init(info)
1018 }
1019 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
1020 let src = pkt.get_buffer();
1021 validate!(src.len() > 8);
1022
1023 let mut mr = MemoryReader::new_read(&src);
1024 let mut br = ByteReader::new(&mut mr);
1025
1026 let mut store = false;
1027 while br.left() > 0 {
1028 let tag = br.read_tag()?;
1029 let size = br.read_u32be()? as usize;
1030 validate!((size as i64) <= br.left());
1031 match &tag {
1032 b"NPAL" => {
1033 validate!((size % 3) == 0);
1034 br.read_buf(&mut self.pic.pal[..size])?;
1035 },
1036 b"XPAL" => {
1037 let cmd = br.read_u32be()?;
1038 match cmd {
1039 0 => {
1040 validate!(size == 0x604);
1041 for el in self.pic.pdelta.iter_mut() {
1042 *el = br.read_u16le()?;
1043 }
1044 for (dst, &src) in self.pic.fpal.iter_mut().zip(self.pic.pal.iter()) {
1045 *dst = u16::from(src) << 7;
1046 }
1047 },
1048 1 => {
1049 validate!(size == 4 || size == 6);
1050 for i in 0..768 {
1051 self.pic.fpal[i] = self.pic.fpal[i].wrapping_add(self.pic.pdelta[i]);
1052 self.pic.pal[i] = (self.pic.fpal[i] >> 7) as u8;
1053 }
e6aaad5c 1054 br.read_skip(size - 4)?;
c17769db
KS
1055 },
1056 2 => {
1057 validate!(size == 0x904);
1058 for el in self.pic.pdelta.iter_mut() {
1059 *el = br.read_u16le()?;
1060 }
1061 br.read_buf(&mut self.pic.pal)?;
1062 },
1063 _ => return Err(DecoderError::InvalidData),
1064 };
1065 },
1066 b"FTCH" => {
1067 br.read_skip(size)?;
1068 self.pic.frm0.copy_from_slice(&self.pic.frm1);
1069 },
1070 b"STOR" => {
1071 store = true;
1072 br.read_skip(size)?;
1073 },
1074 b"FOBJ" => {
1075 validate!(size >= 14);
1076 let end = br.tell() + (size as u64);
1077 let compression = br.read_byte()?;
1078 let cparam = br.read_byte()?;
1079 let x = br.read_u16le()? as i16;
1080 let y = br.read_u16le()? as i16;
1081 let w = br.read_u16le()? as usize;
1082 let h = br.read_u16le()? as usize;
1083 let _ = br.read_u16le()?;
1084 let param2 = br.read_u16le()?;
1085
1086 match compression {
1087 1 | 3 => self.decode_1(&mut br, x, y, w, h, (compression == 1) ^ (self.version != 1))?,
1088 2 => self.decode_2(&mut br, x, y, w, h, size - 14)?,
1089 4 | 33 => self.decode_4(&mut br, x, y, w, h, cparam, param2)?,
1090 5 | 34 => self.decode_5(&mut br, x, y, w, h, cparam, param2)?,
1091 21 | 44 => self.decode_21(&mut br, x, y, w, h, size - 14)?,
1092 23 => self.decode_23(&mut br, x, y, w, h, cparam, param2, self.version == 1)?,
1093 37 => {
1094 let start = br.tell() as usize;
1095 let end = start + size - 14;
1096 let mut mr = MemoryReader::new_read(&src[start..end]);
1097 let mut br = ByteReader::new(&mut mr);
1098 self.decode_37(&mut br, x, y, w, h)?;
1099 },
1100 47 => {
1101 let start = br.tell() as usize;
1102 let end = start + size - 14;
1103 let mut mr = MemoryReader::new_read(&src[start..end]);
1104 let mut br = ByteReader::new(&mut mr);
1105 self.decode_47(&mut br, x, y, w, h)?;
1106 },
1107 48 => {
1108 let start = br.tell() as usize;
1109 let end = start + size - 14;
1110 let mut mr = MemoryReader::new_read(&src[start..end]);
1111 let mut br = ByteReader::new(&mut mr);
1112 self.decode_48(&mut br, x, y, w, h)?;
1113 },
1114 _ => return Err(DecoderError::NotImplemented),
1115 };
1116 validate!(br.tell() <= end);
1117 let tail = end - br.tell();
1118 br.read_skip(tail as usize)?;
1119 if store {
1120 self.pic.frm1.copy_from_slice(&self.pic.frm0);
1121 store = false;
1122 }
1123 },
1124 _ => br.read_skip(size)?,
1125 };
1126 }
1127
1128 let ret = self.pic.get_frame(pkt);
1129
1130 if self.reorder == 2 {
1131 std::mem::swap(&mut self.pic.frm1, &mut self.pic.frm2);
1132 }
1133 if self.reorder != 0 {
1134 std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2);
1135 }
1136 self.reorder = 0;
1137
1138 ret
1139 }
1140 fn flush(&mut self) {
1141 }
1142}
1143
1144impl NAOptionHandler for Smush1Decoder {
1145 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
1146 fn set_options(&mut self, _options: &[NAOption]) { }
1147 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
1148}
1149
1150
1151pub fn get_decoder_video_v1() -> Box<dyn NADecoder + Send> {
1152 Box::new(Smush1Decoder::new())
1153}
1154
1155#[cfg(test)]
1156mod test {
1157 use nihav_core::codecs::RegisteredDecoders;
1158 use nihav_core::demuxers::RegisteredDemuxers;
1159 use nihav_codec_support::test::dec_video::*;
1160 use crate::game_register_all_decoders;
1161 use crate::game_register_all_demuxers;
1162 // samples from Rebel Assault
1163 #[test]
1164 fn test_smush_anim_v1() {
1165 let mut dmx_reg = RegisteredDemuxers::new();
1166 game_register_all_demuxers(&mut dmx_reg);
1167 let mut dec_reg = RegisteredDecoders::new();
1168 game_register_all_decoders(&mut dec_reg);
1169
1170 test_decoding("smush", "smushv1", "assets/Game/smush/c1block.anm", Some(42), &dmx_reg, &dec_reg,
1171 ExpectedTestResult::MD5([0x39339398, 0x7ce83788, 0xaac917d4, 0xaef9d653]));
1172 test_decoding("smush", "smushv1", "assets/Game/smush/c1c3po.anm", Some(42), &dmx_reg, &dec_reg,
1173 ExpectedTestResult::MD5([0x9c1c2422, 0x2121aa7a, 0xc06418bc, 0xd82d704b]));
1174 test_decoding("smush", "smushv1", "assets/Game/smush/o1option.anm", Some(4), &dmx_reg, &dec_reg,
1175 ExpectedTestResult::MD5([0x21ea3ee9, 0x3d88bcee, 0x9b71a87a, 0xc5e0a006]));
1176 }
1177 #[test]
1178 fn test_smush_anim_v2() {
1179 let mut dmx_reg = RegisteredDemuxers::new();
1180 game_register_all_demuxers(&mut dmx_reg);
1181 let mut dec_reg = RegisteredDecoders::new();
1182 game_register_all_decoders(&mut dec_reg);
1183
1184 // sample from The Dig
1185 test_decoding("smush", "smushv1", "assets/Game/smush/PIGOUT.SAN", Some(42), &dmx_reg, &dec_reg,
1186 ExpectedTestResult::MD5([0x74794559, 0x78a1e484, 0x379a1eec, 0x0609e0b2]));
1187 // sample from Full Throttle
1188 test_decoding("smush", "smushv1", "assets/Game/smush/FIRE.SAN", Some(16), &dmx_reg, &dec_reg,
1189 ExpectedTestResult::MD5([0x442f73b9, 0x0b98d80f, 0xee2f0e19, 0xa555a33d]));
1190 // sample from Mortimer and the Riddles of the Medallion
1191 test_decoding("smush", "smushv1", "assets/Game/smush/FOREST1.SAN", Some(24), &dmx_reg, &dec_reg,
1192 ExpectedTestResult::MD5([0xd5b71505, 0x0ffe79dd, 0xc274dbaf, 0x8b952271]));
1193 // sample from Curse of Monkey Island
1194 test_decoding("smush", "smushv1", "assets/Game/smush/ZAP010.SAN", None, &dmx_reg, &dec_reg,
1195 ExpectedTestResult::MD5([0x369839f1, 0x2daab242, 0x23995d80, 0x501fbe09]));
1196 // sample from Jedi Knight: Mysteries of the Sith
1197 test_decoding("smush", "smushv1", "assets/Game/smush/S2L4ECS.SAN", Some(42), &dmx_reg, &dec_reg,
1198 ExpectedTestResult::MD5([0x4525b5f3, 0x9fe5fb23, 0xf5f27980, 0x12589ce1]));
1199 }
1200}
1201
1202const C37_MV: [[i8; 255 * 2]; 3] = [
1203 [
1204 0, 0, 1, 0, 2, 0, 3, 0, 5, 0, 8, 0, 13, 0, 21,
1205 0, -1, 0, -2, 0, -3, 0, -5, 0, -8, 0, -13, 0, -17, 0,
1206 -21, 0, 0, 1, 1, 1, 2, 1, 3, 1, 5, 1, 8, 1, 13,
1207 1, 21, 1, -1, 1, -2, 1, -3, 1, -5, 1, -8, 1, -13, 1,
1208 -17, 1, -21, 1, 0, 2, 1, 2, 2, 2, 3, 2, 5, 2, 8,
1209 2, 13, 2, 21, 2, -1, 2, -2, 2, -3, 2, -5, 2, -8, 2,
1210 -13, 2, -17, 2, -21, 2, 0, 3, 1, 3, 2, 3, 3, 3, 5,
1211 3, 8, 3, 13, 3, 21, 3, -1, 3, -2, 3, -3, 3, -5, 3,
1212 -8, 3, -13, 3, -17, 3, -21, 3, 0, 5, 1, 5, 2, 5, 3,
1213 5, 5, 5, 8, 5, 13, 5, 21, 5, -1, 5, -2, 5, -3, 5,
1214 -5, 5, -8, 5, -13, 5, -17, 5, -21, 5, 0, 8, 1, 8, 2,
1215 8, 3, 8, 5, 8, 8, 8, 13, 8, 21, 8, -1, 8, -2, 8,
1216 -3, 8, -5, 8, -8, 8, -13, 8, -17, 8, -21, 8, 0, 13, 1,
1217 13, 2, 13, 3, 13, 5, 13, 8, 13, 13, 13, 21, 13, -1, 13,
1218 -2, 13, -3, 13, -5, 13, -8, 13, -13, 13, -17, 13, -21, 13, 0,
1219 21, 1, 21, 2, 21, 3, 21, 5, 21, 8, 21, 13, 21, 21, 21,
1220 -1, 21, -2, 21, -3, 21, -5, 21, -8, 21, -13, 21, -17, 21, -21,
1221 21, 0, -1, 1, -1, 2, -1, 3, -1, 5, -1, 8, -1, 13, -1,
1222 21, -1, -1, -1, -2, -1, -3, -1, -5, -1, -8, -1, -13, -1, -17,
1223 -1, -21, -1, 0, -2, 1, -2, 2, -2, 3, -2, 5, -2, 8, -2,
1224 13, -2, 21, -2, -1, -2, -2, -2, -3, -2, -5, -2, -8, -2, -13,
1225 -2, -17, -2, -21, -2, 0, -3, 1, -3, 2, -3, 3, -3, 5, -3,
1226 8, -3, 13, -3, 21, -3, -1, -3, -2, -3, -3, -3, -5, -3, -8,
1227 -3, -13, -3, -17, -3, -21, -3, 0, -5, 1, -5, 2, -5, 3, -5,
1228 5, -5, 8, -5, 13, -5, 21, -5, -1, -5, -2, -5, -3, -5, -5,
1229 -5, -8, -5, -13, -5, -17, -5, -21, -5, 0, -8, 1, -8, 2, -8,
1230 3, -8, 5, -8, 8, -8, 13, -8, 21, -8, -1, -8, -2, -8, -3,
1231 -8, -5, -8, -8, -8, -13, -8, -17, -8, -21, -8, 0, -13, 1, -13,
1232 2, -13, 3, -13, 5, -13, 8, -13, 13, -13, 21, -13, -1, -13, -2,
1233 -13, -3, -13, -5, -13, -8, -13, -13, -13, -17, -13, -21, -13, 0, -17,
1234 1, -17, 2, -17, 3, -17, 5, -17, 8, -17, 13, -17, 21, -17, -1,
1235 -17, -2, -17, -3, -17, -5, -17, -8, -17, -13, -17, -17, -17, -21, -17,
1236 0, -21, 1, -21, 2, -21, 3, -21, 5, -21, 8, -21, 13, -21, 21,
1237 -21, -1, -21, -2, -21, -3, -21, -5, -21, -8, -21, -13, -21, -17, -21
1238 ], [
1239 0, 0, -8, -29, 8, -29, -18, -25, 17, -25, 0, -23, -6, -22, 6,
1240 -22, -13, -19, 12, -19, 0, -18, 25, -18, -25, -17, -5, -17, 5, -17,
1241 -10, -15, 10, -15, 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, -8,
1242 -11, -2, -11, 0, -11, 2, -11, 8, -11, -15, -10, -4, -10, 4, -10,
1243 15, -10, -6, -9, -1, -9, 1, -9, 6, -9, -29, -8, -11, -8, -8,
1244 -8, -3, -8, 3, -8, 8, -8, 11, -8, 29, -8, -5, -7, -2, -7,
1245 0, -7, 2, -7, 5, -7, -22, -6, -9, -6, -6, -6, -3, -6, -1,
1246 -6, 1, -6, 3, -6, 6, -6, 9, -6, 22, -6, -17, -5, -7, -5,
1247 -4, -5, -2, -5, 0, -5, 2, -5, 4, -5, 7, -5, 17, -5, -13,
1248 -4, -10, -4, -5, -4, -3, -4, -1, -4, 0, -4, 1, -4, 3, -4,
1249 5, -4, 10, -4, 13, -4, -8, -3, -6, -3, -4, -3, -3, -3, -2,
1250 -3, -1, -3, 0, -3, 1, -3, 2, -3, 4, -3, 6, -3, 8, -3,
1251 -11, -2, -7, -2, -5, -2, -3, -2, -2, -2, -1, -2, 0, -2, 1,
1252 -2, 2, -2, 3, -2, 5, -2, 7, -2, 11, -2, -9, -1, -6, -1,
1253 -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3,
1254 -1, 4, -1, 6, -1, 9, -1, -31, 0, -23, 0, -18, 0, -14, 0,
1255 -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 0,
1256 -31, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
1257 14, 0, 18, 0, 23, 0, 31, 0, -9, 1, -6, 1, -4, 1, -3,
1258 1, -2, 1, -1, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
1259 6, 1, 9, 1, -11, 2, -7, 2, -5, 2, -3, 2, -2, 2, -1,
1260 2, 0, 2, 1, 2, 2, 2, 3, 2, 5, 2, 7, 2, 11, 2,
1261 -8, 3, -6, 3, -4, 3, -2, 3, -1, 3, 0, 3, 1, 3, 2,
1262 3, 3, 3, 4, 3, 6, 3, 8, 3, -13, 4, -10, 4, -5, 4,
1263 -3, 4, -1, 4, 0, 4, 1, 4, 3, 4, 5, 4, 10, 4, 13,
1264 4, -17, 5, -7, 5, -4, 5, -2, 5, 0, 5, 2, 5, 4, 5,
1265 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, -3, 6, -1, 6, 1,
1266 6, 3, 6, 6, 6, 9, 6, 22, 6, -5, 7, -2, 7, 0, 7,
1267 2, 7, 5, 7, -29, 8, -11, 8, -8, 8, -3, 8, 3, 8, 8,
1268 8, 11, 8, 29, 8, -6, 9, -1, 9, 1, 9, 6, 9, -15, 10,
1269 -4, 10, 4, 10, 15, 10, -8, 11, -2, 11, 0, 11, 2, 11, 8,
1270 11, 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, -10, 15, 10, 15,
1271 -5, 17, 5, 17, 25, 17, -25, 18, 0, 18, -12, 19, 13, 19, -6,
1272 22, 6, 22, 0, 23, -17, 25, 18, 25, -8, 29, 8, 29, 0, 31
1273 ], [
1274 0, 0, -6, -22, 6, -22, -13, -19, 12, -19, 0, -18, -5, -17, 5,
1275 -17, -10, -15, 10, -15, 0, -14, -4, -13, 4, -13, 19, -13, -19, -12,
1276 -8, -11, -2, -11, 0, -11, 2, -11, 8, -11, -15, -10, -4, -10, 4,
1277 -10, 15, -10, -6, -9, -1, -9, 1, -9, 6, -9, -11, -8, -8, -8,
1278 -3, -8, 0, -8, 3, -8, 8, -8, 11, -8, -5, -7, -2, -7, 0,
1279 -7, 2, -7, 5, -7, -22, -6, -9, -6, -6, -6, -3, -6, -1, -6,
1280 1, -6, 3, -6, 6, -6, 9, -6, 22, -6, -17, -5, -7, -5, -4,
1281 -5, -2, -5, -1, -5, 0, -5, 1, -5, 2, -5, 4, -5, 7, -5,
1282 17, -5, -13, -4, -10, -4, -5, -4, -3, -4, -2, -4, -1, -4, 0,
1283 -4, 1, -4, 2, -4, 3, -4, 5, -4, 10, -4, 13, -4, -8, -3,
1284 -6, -3, -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, 1, -3, 2,
1285 -3, 3, -3, 4, -3, 6, -3, 8, -3, -11, -2, -7, -2, -5, -2,
1286 -4, -2, -3, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 3,
1287 -2, 4, -2, 5, -2, 7, -2, 11, -2, -9, -1, -6, -1, -5, -1,
1288 -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3,
1289 -1, 4, -1, 5, -1, 6, -1, 9, -1, -23, 0, -18, 0, -14, 0,
1290 -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 0,
1291 -23, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
1292 14, 0, 18, 0, 23, 0, -9, 1, -6, 1, -5, 1, -4, 1, -3,
1293 1, -2, 1, -1, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
1294 5, 1, 6, 1, 9, 1, -11, 2, -7, 2, -5, 2, -4, 2, -3,
1295 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2,
1296 5, 2, 7, 2, 11, 2, -8, 3, -6, 3, -4, 3, -3, 3, -2,
1297 3, -1, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, 6, 3,
1298 8, 3, -13, 4, -10, 4, -5, 4, -3, 4, -2, 4, -1, 4, 0,
1299 4, 1, 4, 2, 4, 3, 4, 5, 4, 10, 4, 13, 4, -17, 5,
1300 -7, 5, -4, 5, -2, 5, -1, 5, 0, 5, 1, 5, 2, 5, 4,
1301 5, 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, -3, 6, -1, 6,
1302 1, 6, 3, 6, 6, 6, 9, 6, 22, 6, -5, 7, -2, 7, 0,
1303 7, 2, 7, 5, 7, -11, 8, -8, 8, -3, 8, 0, 8, 3, 8,
1304 8, 8, 11, 8, -6, 9, -1, 9, 1, 9, 6, 9, -15, 10, -4,
1305 10, 4, 10, 15, 10, -8, 11, -2, 11, 0, 11, 2, 11, 8, 11,
1306 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, -5,
1307 17, 5, 17, 0, 18, -12, 19, 13, 19, -6, 22, 6, 22, 0, 23
1308 ]
1309];
1310
1311const C47_MV: [[[i8; 2]; 255]; 2] = [
1312 [
1313 [ 0, 0], [ -1, -43], [ 6, -43], [ -9, -42], [ 13, -41],
1314 [-16, -40], [ 19, -39], [-23, -36], [ 26, -34], [ -2, -33],
1315 [ 4, -33], [-29, -32], [ -9, -32], [ 11, -31], [-16, -29],
1316 [ 32, -29], [ 18, -28], [-34, -26], [-22, -25], [ -1, -25],
1317 [ 3, -25], [ -7, -24], [ 8, -24], [ 24, -23], [ 36, -23],
1318 [-12, -22], [ 13, -21], [-38, -20], [ 0, -20], [-27, -19],
1319 [ -4, -19], [ 4, -19], [-17, -18], [ -8, -17], [ 8, -17],
1320 [ 18, -17], [ 28, -17], [ 39, -17], [-12, -15], [ 12, -15],
1321 [-21, -14], [ -1, -14], [ 1, -14], [-41, -13], [ -5, -13],
1322 [ 5, -13], [ 21, -13], [-31, -12], [-15, -11], [ -8, -11],
1323 [ 8, -11], [ 15, -11], [ -2, -10], [ 1, -10], [ 31, -10],
1324 [-23, -9], [-11, -9], [ -5, -9], [ 4, -9], [ 11, -9],
1325 [ 42, -9], [ 6, -8], [ 24, -8], [-18, -7], [ -7, -7],
1326 [ -3, -7], [ -1, -7], [ 2, -7], [ 18, -7], [-43, -6],
1327 [-13, -6], [ -4, -6], [ 4, -6], [ 8, -6], [-33, -5],
1328 [ -9, -5], [ -2, -5], [ 0, -5], [ 2, -5], [ 5, -5],
1329 [ 13, -5], [-25, -4], [ -6, -4], [ -3, -4], [ 3, -4],
1330 [ 9, -4], [-19, -3], [ -7, -3], [ -4, -3], [ -2, -3],
1331 [ -1, -3], [ 0, -3], [ 1, -3], [ 2, -3], [ 4, -3],
1332 [ 6, -3], [ 33, -3], [-14, -2], [-10, -2], [ -5, -2],
1333 [ -3, -2], [ -2, -2], [ -1, -2], [ 0, -2], [ 1, -2],
1334 [ 2, -2], [ 3, -2], [ 5, -2], [ 7, -2], [ 14, -2],
1335 [ 19, -2], [ 25, -2], [ 43, -2], [ -7, -1], [ -3, -1],
1336 [ -2, -1], [ -1, -1], [ 0, -1], [ 1, -1], [ 2, -1],
1337 [ 3, -1], [ 10, -1], [ -5, 0], [ -3, 0], [ -2, 0],
1338 [ -1, 0], [ 1, 0], [ 2, 0], [ 3, 0], [ 5, 0],
1339 [ 7, 0], [-10, 1], [ -7, 1], [ -3, 1], [ -2, 1],
1340 [ -1, 1], [ 0, 1], [ 1, 1], [ 2, 1], [ 3, 1],
1341 [-43, 2], [-25, 2], [-19, 2], [-14, 2], [ -5, 2],
1342 [ -3, 2], [ -2, 2], [ -1, 2], [ 0, 2], [ 1, 2],
1343 [ 2, 2], [ 3, 2], [ 5, 2], [ 7, 2], [ 10, 2],
1344 [ 14, 2], [-33, 3], [ -6, 3], [ -4, 3], [ -2, 3],
1345 [ -1, 3], [ 0, 3], [ 1, 3], [ 2, 3], [ 4, 3],
1346 [ 19, 3], [ -9, 4], [ -3, 4], [ 3, 4], [ 7, 4],
1347 [ 25, 4], [-13, 5], [ -5, 5], [ -2, 5], [ 0, 5],
1348 [ 2, 5], [ 5, 5], [ 9, 5], [ 33, 5], [ -8, 6],
1349 [ -4, 6], [ 4, 6], [ 13, 6], [ 43, 6], [-18, 7],
1350 [ -2, 7], [ 0, 7], [ 2, 7], [ 7, 7], [ 18, 7],
1351 [-24, 8], [ -6, 8], [-42, 9], [-11, 9], [ -4, 9],
1352 [ 5, 9], [ 11, 9], [ 23, 9], [-31, 10], [ -1, 10],
1353 [ 2, 10], [-15, 11], [ -8, 11], [ 8, 11], [ 15, 11],
1354 [ 31, 12], [-21, 13], [ -5, 13], [ 5, 13], [ 41, 13],
1355 [ -1, 14], [ 1, 14], [ 21, 14], [-12, 15], [ 12, 15],
1356 [-39, 17], [-28, 17], [-18, 17], [ -8, 17], [ 8, 17],
1357 [ 17, 18], [ -4, 19], [ 0, 19], [ 4, 19], [ 27, 19],
1358 [ 38, 20], [-13, 21], [ 12, 22], [-36, 23], [-24, 23],
1359 [ -8, 24], [ 7, 24], [ -3, 25], [ 1, 25], [ 22, 25],
1360 [ 34, 26], [-18, 28], [-32, 29], [ 16, 29], [-11, 31],
1361 [ 9, 32], [ 29, 32], [ -4, 33], [ 2, 33], [-26, 34],
1362 [ 23, 36], [-19, 39], [ 16, 40], [-13, 41], [ 9, 42],
1363 [ -6, 43], [ 1, 43], [ 0, 0], [ 0, 0], [ 0, 0],
1364 ], [
1365 [ 0, 0], [ 1, 0], [ 2, 0], [ 3, 0], [ 5, 0],
1366 [ 8, 0], [ 13, 0], [ 21, 0], [ -1, 0], [ -2, 0],
1367 [ -3, 0], [ -5, 0], [ -8, 0], [-13, 0], [-17, 0],
1368 [-21, 0], [ 0, 1], [ 1, 1], [ 2, 1], [ 3, 1],
1369 [ 5, 1], [ 8, 1], [ 13, 1], [ 21, 1], [ -1, 1],
1370 [ -2, 1], [ -3, 1], [ -5, 1], [ -8, 1], [-13, 1],
1371 [-17, 1], [-21, 1], [ 0, 2], [ 1, 2], [ 2, 2],
1372 [ 3, 2], [ 5, 2], [ 8, 2], [ 13, 2], [ 21, 2],
1373 [ -1, 2], [ -2, 2], [ -3, 2], [ -5, 2], [ -8, 2],
1374 [-13, 2], [-17, 2], [-21, 2], [ 0, 3], [ 1, 3],
1375 [ 2, 3], [ 3, 3], [ 5, 3], [ 8, 3], [ 13, 3],
1376 [ 21, 3], [ -1, 3], [ -2, 3], [ -3, 3], [ -5, 3],
1377 [ -8, 3], [-13, 3], [-17, 3], [-21, 3], [ 0, 5],
1378 [ 1, 5], [ 2, 5], [ 3, 5], [ 5, 5], [ 8, 5],
1379 [ 13, 5], [ 21, 5], [ -1, 5], [ -2, 5], [ -3, 5],
1380 [ -5, 5], [ -8, 5], [-13, 5], [-17, 5], [-21, 5],
1381 [ 0, 8], [ 1, 8], [ 2, 8], [ 3, 8], [ 5, 8],
1382 [ 8, 8], [ 13, 8], [ 21, 8], [ -1, 8], [ -2, 8],
1383 [ -3, 8], [ -5, 8], [ -8, 8], [-13, 8], [-17, 8],
1384 [-21, 8], [ 0, 13], [ 1, 13], [ 2, 13], [ 3, 13],
1385 [ 5, 13], [ 8, 13], [ 13, 13], [ 21, 13], [ -1, 13],
1386 [ -2, 13], [ -3, 13], [ -5, 13], [ -8, 13], [-13, 13],
1387 [-17, 13], [-21, 13], [ 0, 21], [ 1, 21], [ 2, 21],
1388 [ 3, 21], [ 5, 21], [ 8, 21], [ 13, 21], [ 21, 21],
1389 [ -1, 21], [ -2, 21], [ -3, 21], [ -5, 21], [ -8, 21],
1390 [-13, 21], [-17, 21], [-21, 21], [ 0, -1], [ 1, -1],
1391 [ 2, -1], [ 3, -1], [ 5, -1], [ 8, -1], [ 13, -1],
1392 [ 21, -1], [ -1, -1], [ -2, -1], [ -3, -1], [ -5, -1],
1393 [ -8, -1], [-13, -1], [-17, -1], [-21, -1], [ 0, -2],
1394 [ 1, -2], [ 2, -2], [ 3, -2], [ 5, -2], [ 8, -2],
1395 [ 13, -2], [ 21, -2], [ -1, -2], [ -2, -2], [ -3, -2],
1396 [ -5, -2], [ -8, -2], [-13, -2], [-17, -2], [-21, -2],
1397 [ 0, -3], [ 1, -3], [ 2, -3], [ 3, -3], [ 5, -3],
1398 [ 8, -3], [ 13, -3], [ 21, -3], [ -1, -3], [ -2, -3],
1399 [ -3, -3], [ -5, -3], [ -8, -3], [-13, -3], [-17, -3],
1400 [-21, -3], [ 0, -5], [ 1, -5], [ 2, -5], [ 3, -5],
1401 [ 5, -5], [ 8, -5], [ 13, -5], [ 21, -5], [ -1, -5],
1402 [ -2, -5], [ -3, -5], [ -5, -5], [ -8, -5], [-13, -5],
1403 [-17, -5], [-21, -5], [ 0, -8], [ 1, -8], [ 2, -8],
1404 [ 3, -8], [ 5, -8], [ 8, -8], [ 13, -8], [ 21, -8],
1405 [ -1, -8], [ -2, -8], [ -3, -8], [ -5, -8], [ -8, -8],
1406 [-13, -8], [-17, -8], [-21, -8], [ 0, -13], [ 1, -13],
1407 [ 2, -13], [ 3, -13], [ 5, -13], [ 8, -13], [ 13, -13],
1408 [ 21, -13], [ -1, -13], [ -2, -13], [ -3, -13], [ -5, -13],
1409 [ -8, -13], [-13, -13], [-17, -13], [-21, -13], [ 0, -17],
1410 [ 1, -17], [ 2, -17], [ 3, -17], [ 5, -17], [ 8, -17],
1411 [ 13, -17], [ 21, -17], [ -1, -17], [ -2, -17], [ -3, -17],
1412 [ -5, -17], [ -8, -17], [-13, -17], [-17, -17], [-21, -17],
1413 [ 0, -21], [ 1, -21], [ 2, -21], [ 3, -21], [ 5, -21],
1414 [ 8, -21], [ 13, -21], [ 21, -21], [ -1, -21], [ -2, -21],
1415 [ -3, -21], [ -5, -21], [ -8, -21], [-13, -21], [-17, -21]
1416 ]
1417];