]>
Commit | Line | Data |
---|---|---|
c17769db KS |
1 | use nihav_core::codecs::*; |
2 | use nihav_core::io::byteio::*; | |
3 | ||
4 | struct Glyphs { | |
5 | data: [[[u8; 16]; 256]; 2], | |
6 | glyph8: [[u8; 64]; 256], | |
7 | glyph8_init: bool, | |
8 | } | |
9 | ||
10 | impl 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 | ||
153 | struct 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 | ||
165 | impl 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(); | |
183 | self.width = (self.width + 7) & !7; | |
184 | self.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 | ||
272 | fn 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)] | |
287 | fn 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 | ||
351 | macro_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 | ||
384 | fn 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 | ||
395 | struct Smush1Decoder { | |
396 | glyphs: Glyphs, | |
397 | pic: FrameData, | |
398 | version: u8, | |
399 | prev_seq: u16, | |
400 | reorder: u8, | |
401 | filter: [[u8; 256]; 256], | |
402 | } | |
403 | ||
404 | impl 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 | ||
1011 | impl 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 | ||
1144 | impl 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 | ||
1151 | pub fn get_decoder_video_v1() -> Box<dyn NADecoder + Send> { | |
1152 | Box::new(Smush1Decoder::new()) | |
1153 | } | |
1154 | ||
1155 | #[cfg(test)] | |
1156 | mod 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 | ||
1202 | const 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 | ||
1311 | const 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 | ]; |