]>
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) { | |
cb56d166 KS |
275 | for el in row[..4].iter_mut() { |
276 | *el = if pos >= 0 && (pos as usize) < w + (h - 1) * stride { | |
c17769db KS |
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 | } | |
c17769db KS |
481 | fn decode_2(&mut self, br: &mut ByteReader, x: i16, y: i16, _w: usize, _h: usize, len: usize) -> DecoderResult<()> { |
482 | ||
483 | validate!((len & 3) == 0); | |
484 | let mut xpos = x; | |
485 | let mut ypos = y; | |
486 | for _ in 0..len/4 { | |
487 | let xoff = br.read_u16le()? as i16; | |
488 | let yoff = i16::from(br.read_byte()?); | |
489 | let pix = br.read_byte()?; | |
490 | ||
491 | xpos += xoff; | |
492 | ypos += yoff; | |
493 | self.pic.set_pixel(xpos, ypos, 0, 0, pix); | |
494 | } | |
495 | Ok(()) | |
496 | } | |
497 | #[allow(clippy::too_many_arguments)] | |
498 | fn decode_4(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, mode: u8, add: u16) -> DecoderResult<()> { | |
499 | self.glyphs.make_glyphs_4(mode); | |
500 | self.glyphs.read_additional(br, add)?; | |
501 | ||
502 | for col in (0..w).step_by(4) { | |
503 | let mut mask = 0; | |
504 | let mut bits = 0; | |
505 | for row in (0..h).step_by(4) { | |
506 | let bit = if add > 0 { | |
507 | if bits == 0 { | |
508 | mask = br.read_byte()?; | |
509 | bits = 8; | |
510 | } | |
511 | let bit = (mask & 0x80) != 0; | |
512 | mask <<= 1; | |
513 | bits -= 1; | |
514 | bit | |
515 | } else { | |
516 | false | |
517 | }; | |
518 | ||
519 | let tile_no = br.read_byte()? as usize; | |
520 | if !bit && (tile_no == 0x80) { | |
521 | continue; | |
522 | } | |
523 | let src = &self.glyphs.data[bit as usize][tile_no]; | |
524 | for (y1, srow) in src.chunks(4).enumerate() { | |
525 | for (x1, &pix) in srow.iter().enumerate() { | |
526 | self.pic.set_pixel(x, y, col + x1, row + y1, pix); | |
527 | } | |
528 | } | |
529 | if !bit { | |
530 | self.pic.loop_filter(x, y, col, row); | |
531 | } | |
532 | } | |
533 | } | |
534 | ||
535 | Ok(()) | |
536 | } | |
537 | #[allow(clippy::too_many_arguments)] | |
538 | fn decode_5(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, mode: u8, add: u16) -> DecoderResult<()> { | |
539 | self.glyphs.make_glyphs_5(mode); | |
540 | self.glyphs.read_additional(br, add)?; | |
541 | ||
542 | for col in (0..w).step_by(4) { | |
543 | let mut mask = 0; | |
544 | let mut bits = 0; | |
545 | for row in (0..h).step_by(4) { | |
546 | let bit = if add > 0 { | |
547 | if bits == 0 { | |
548 | mask = br.read_byte()?; | |
549 | bits = 8; | |
550 | } | |
551 | let bit = (mask & 0x80) != 0; | |
552 | mask <<= 1; | |
553 | bits -= 1; | |
554 | bit | |
555 | } else { | |
556 | false | |
557 | }; | |
558 | ||
559 | let tile_no = br.read_byte()? as usize; | |
560 | let src = &self.glyphs.data[bit as usize][tile_no]; | |
561 | for (y1, srow) in src.chunks(4).enumerate() { | |
562 | for (x1, &pix) in srow.iter().enumerate() { | |
563 | self.pic.set_pixel(x, y, col + x1, row + y1, pix); | |
564 | } | |
565 | } | |
566 | if !bit { | |
567 | self.pic.loop_filter(x, y, col, row); | |
568 | } | |
569 | } | |
570 | } | |
571 | ||
572 | Ok(()) | |
573 | } | |
574 | fn decode_21(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, size: usize) -> DecoderResult<()> { | |
575 | let end = br.tell() + (size as u64); | |
576 | for yy in 0..h { | |
577 | if br.tell() >= end { break; } | |
578 | let len = u64::from(br.read_u16le()?); | |
579 | let end = br.tell() + len; | |
580 | let mut xx = 0; | |
581 | let mut skip = true; | |
582 | while (br.tell() < end) && (xx <= w) { | |
583 | let len = br.read_u16le()? as usize; | |
584 | if !skip { | |
585 | for _ in 0..=len { | |
586 | let pix = br.read_byte()?; | |
587 | self.pic.set_pixel(x, y, xx, yy, pix); | |
588 | xx += 1; | |
589 | } | |
590 | } else { | |
591 | for _ in 0..len { | |
592 | self.pic.set_pixel(x, y, xx, yy, 0); | |
593 | xx += 1; | |
594 | } | |
595 | } | |
596 | skip = !skip; | |
597 | } | |
598 | validate!(br.tell() == end && xx == w + 1); | |
599 | } | |
600 | ||
601 | Ok(()) | |
602 | } | |
603 | #[allow(clippy::too_many_arguments)] | |
604 | fn decode_23(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize, bias: u8, add: u16, old: bool) -> DecoderResult<()> { | |
605 | let mut lut = [0; 256]; | |
606 | if old { | |
607 | for (i, el) in lut.iter_mut().enumerate() { | |
608 | *el = (i as u8).wrapping_add(bias.wrapping_sub(0x30)); | |
609 | } | |
610 | } else if add != 256 { | |
611 | for (i, el) in lut.iter_mut().enumerate() { | |
612 | *el = (i as u8).wrapping_add(add as u8); | |
613 | } | |
614 | } else { | |
615 | br.read_buf(&mut lut)?; | |
616 | } | |
617 | for yy in 0..h { | |
618 | let len = u64::from(br.read_u16le()?); | |
619 | let end = br.tell() + len; | |
620 | let mut xx = 0; | |
621 | let mut skip = true; | |
622 | while (br.tell() < end) && (xx <= w) { | |
623 | let len = br.read_byte()? as usize; | |
624 | if !skip { | |
625 | for _ in 0..len { | |
626 | let pix = self.pic.get_pixel(x, y, xx, yy); | |
627 | self.pic.set_pixel(x, y, xx, yy, lut[pix as usize]); | |
628 | xx += 1; | |
629 | } | |
630 | } else { | |
631 | xx += len; | |
632 | } | |
633 | skip = !skip; | |
634 | } | |
635 | validate!(br.tell() == end && xx == w + 1); | |
636 | } | |
637 | ||
638 | Ok(()) | |
639 | } | |
640 | fn decode_37(&mut self, br: &mut ByteReader, x: i16, y: i16, mut w: usize, mut h: usize) -> DecoderResult<()> { | |
641 | let compr = br.read_byte()?; | |
642 | let mv_off = br.read_byte()? as usize; | |
643 | validate!(mv_off <= 2); | |
644 | let seq = br.read_u16le()?; | |
645 | let _unp_size = br.read_u32le()?; | |
646 | let _packed_size = br.read_u32le()?; | |
647 | let flags = br.read_byte()?; | |
648 | br.read_skip(3)?; | |
649 | ||
650 | w = (w + 3) & !3; | |
651 | h = (h + 3) & !3; | |
652 | ||
653 | validate!(x >= 0 && y >= 0); | |
654 | let x = x as usize; | |
655 | let y = y as usize; | |
656 | validate!((x + w <= self.pic.width) && (y + h <= self.pic.height)); | |
657 | ||
658 | if compr == 0 || compr == 2 { | |
659 | for el in self.pic.frm1.iter_mut() { | |
660 | *el = 0; | |
661 | } | |
662 | for el in self.pic.frm2.iter_mut() { | |
663 | *el = 0; | |
664 | } | |
665 | } else if ((seq & 1) != 0) || ((flags & 1) == 0) { | |
666 | std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2); | |
667 | } | |
668 | ||
669 | let stride = self.pic.width; | |
670 | let dst = &mut self.pic.frm0[x + y * stride..]; | |
671 | let prv = &self.pic.frm2[x + y * stride..]; | |
672 | match compr { | |
673 | 0 => { | |
674 | for line in dst.chunks_mut(stride).take(h) { | |
675 | br.read_buf(&mut line[..w])?; | |
676 | } | |
677 | }, | |
678 | 1 => { | |
679 | let mut len = -1; | |
680 | let mut run = false; | |
681 | let mut code = 0; | |
682 | for (row_no, row) in dst.chunks_mut(stride * 4).take(h / 4).enumerate() { | |
683 | for col in (0..w).step_by(4) { | |
684 | let skip_code = if len < 0 { | |
685 | let op = br.read_byte()?; | |
686 | len = (op >> 1) as i8; | |
687 | run = (op & 1) != 0; | |
688 | false | |
689 | } else { | |
690 | run | |
691 | }; | |
692 | if !skip_code { | |
693 | code = br.read_byte()?; | |
694 | if code == 0xFF { | |
695 | len -= 1; | |
696 | for drow in row[col..].chunks_mut(stride) { | |
697 | for el in drow[..4].iter_mut() { | |
698 | if len < 0 { | |
699 | let op = br.read_byte()?; | |
700 | len = (op >> 1) as i8; | |
701 | run = (op & 1) != 0; | |
702 | if run { | |
703 | code = br.read_byte()?; | |
704 | } | |
705 | } | |
706 | if run { | |
707 | *el = code; | |
708 | } else { | |
709 | *el = br.read_byte()?; | |
710 | } | |
711 | len -= 1; | |
712 | } | |
713 | } | |
714 | continue; | |
715 | } | |
716 | } | |
717 | let idx = code as usize; | |
718 | let mx = C37_MV[mv_off][idx * 2] as isize; | |
719 | let my = C37_MV[mv_off][idx * 2 + 1] as isize; | |
720 | do_mc(&mut row[col..], &self.pic.frm2, stride, | |
721 | (x as isize) + (col as isize) + mx, | |
722 | (y as isize) + (row_no as isize) * 4 + my, | |
723 | self.pic.width, self.pic.height); | |
724 | len -= 1; | |
725 | } | |
726 | } | |
727 | }, | |
728 | 2 => { | |
729 | Self::decode_rle(br, dst, w, h, stride)?; | |
730 | }, | |
731 | 3 | 4 => { | |
732 | let has_fills = (flags & 4) != 0; | |
733 | let has_skips = compr == 4; | |
734 | let mut skip_run = 0; | |
735 | for (row_no, row) in dst.chunks_mut(stride * 4).take(h / 4).enumerate() { | |
736 | for col in (0..w).step_by(4) { | |
737 | if skip_run > 0 { | |
738 | for (drow, srow) in row[col..].chunks_mut(stride).zip(prv[col + row_no * 4 * stride..].chunks(stride)) { | |
739 | drow[..4].copy_from_slice(&srow[..4]); | |
740 | } | |
741 | skip_run -= 1; | |
742 | continue; | |
743 | } | |
744 | let opcode = br.read_byte()?; | |
745 | match opcode { | |
746 | 0xFF => { | |
747 | for drow in row[col..].chunks_mut(stride) { | |
748 | br.read_buf(&mut drow[..4])?; | |
749 | } | |
750 | }, | |
751 | 0xFE if has_fills => { | |
752 | for drow in row[col..].chunks_mut(stride) { | |
753 | let clr = br.read_byte()?; | |
754 | for el in drow[..4].iter_mut() { | |
755 | *el = clr; | |
756 | } | |
757 | } | |
758 | }, | |
759 | 0xFD if has_fills => { | |
760 | let clr = br.read_byte()?; | |
761 | for drow in row[col..].chunks_mut(stride) { | |
762 | for el in drow[..4].iter_mut() { | |
763 | *el = clr; | |
764 | } | |
765 | } | |
766 | }, | |
767 | 0 if has_skips => { | |
768 | skip_run = br.read_byte()?; | |
769 | for (drow, srow) in row[col..].chunks_mut(stride).zip(prv[col + row_no * 4 * stride..].chunks(stride)) { | |
770 | drow[..4].copy_from_slice(&srow[..4]); | |
771 | } | |
772 | }, | |
773 | _ => { | |
774 | let idx = opcode as usize; | |
775 | let mx = C37_MV[mv_off][idx * 2] as isize; | |
776 | let my = C37_MV[mv_off][idx * 2 + 1] as isize; | |
777 | do_mc(&mut row[col..], &self.pic.frm2, stride, | |
778 | (x as isize) + (col as isize) + mx, | |
779 | (y as isize) + (row_no as isize) * 4 + my, | |
780 | self.pic.width, self.pic.height); | |
781 | }, | |
782 | }; | |
783 | } | |
784 | } | |
785 | }, | |
786 | _ => return Err(DecoderError::InvalidData), | |
787 | }; | |
788 | ||
789 | Ok(()) | |
790 | } | |
791 | fn decode_47(&mut self, br: &mut ByteReader, x: i16, y: i16, w: usize, h: usize) -> DecoderResult<()> { | |
792 | let seq = br.read_u16le()?; | |
793 | let compr = br.read_byte()?; | |
794 | let reorder = br.read_byte()?; | |
795 | let flags = br.read_byte()?; | |
796 | br.read_skip(3)?; | |
797 | let mut clr = [0; 6]; | |
798 | br.read_buf(&mut clr)?; | |
799 | let _dec_size = br.read_u32le()?; | |
800 | br.read_skip(4)?; | |
801 | br.read_skip(4)?; | |
802 | ||
803 | if (flags & 1) != 0 { | |
804 | for i in 0..256 { | |
805 | for j in i..256 { | |
806 | let val = br.read_byte()?; | |
807 | self.filter[i][j] = val; | |
808 | self.filter[j][i] = val; | |
809 | } | |
810 | } | |
811 | } | |
812 | ||
813 | if compr == 2 && !self.glyphs.glyph8_init { | |
814 | self.glyphs.make_glyphs_47(); | |
815 | } | |
816 | ||
817 | if seq == 0 { | |
818 | for el in self.pic.frm1.iter_mut() { | |
819 | *el = 0; | |
820 | } | |
821 | for el in self.pic.frm2.iter_mut() { | |
822 | *el = 0; | |
823 | } | |
824 | } | |
825 | ||
826 | validate!(x >= 0 && y >= 0); | |
827 | let x = x as usize; | |
828 | let y = y as usize; | |
829 | validate!((x + w <= self.pic.width) && (y + h <= self.pic.height)); | |
830 | ||
831 | let stride = self.pic.width; | |
832 | let dst = &mut self.pic.frm0[x + y * stride..]; | |
833 | match compr { | |
834 | 0 => { | |
835 | for line in dst.chunks_mut(stride).take(h) { | |
836 | br.read_buf(&mut line[..w])?; | |
837 | } | |
838 | }, | |
839 | 1 => { | |
840 | for row in dst.chunks_mut(stride * 2).take((h + 1) / 2) { | |
841 | for col in (0..w).step_by(2) { | |
842 | let pix = br.read_byte()?; | |
843 | row[col] = pix; | |
844 | row[col + 1] = pix; | |
845 | row[col + stride] = pix; | |
846 | row[col + stride + 1] = pix; | |
847 | } | |
848 | } | |
849 | }, | |
850 | 2 => { | |
851 | for (row_no, row) in dst.chunks_mut(stride * 8).take((h + 7) / 8).enumerate() { | |
852 | for col in (0..w).step_by(8) { | |
853 | do_block47(br, &mut row[col..], &self.pic.frm1, &self.pic.frm2, col, row_no * 8, stride, 8, &clr, &self.glyphs)?; | |
854 | } | |
855 | } | |
856 | }, | |
857 | 3 => { | |
858 | self.pic.frm0.copy_from_slice(&self.pic.frm2); | |
859 | }, | |
860 | 4 => { | |
861 | self.pic.frm0.copy_from_slice(&self.pic.frm1); | |
862 | }, | |
863 | 5 => { | |
864 | Self::decode_rle(br, dst, w, h, stride)?; | |
865 | }, | |
866 | _ => return Err(DecoderError::InvalidData), | |
867 | }; | |
868 | ||
869 | self.reorder = if seq == 0 || seq == self.prev_seq + 1 { reorder } else { 0 }; | |
870 | self.prev_seq = seq; | |
871 | ||
872 | Ok(()) | |
873 | } | |
874 | fn decode_48(&mut self, br: &mut ByteReader, x: i16, y: i16, mut w: usize, mut h: usize) -> DecoderResult<()> { | |
875 | let compr = br.read_byte()?; | |
876 | let mvsel = br.read_byte()? as usize; | |
877 | validate!(mvsel < 2); | |
878 | let _seq = br.read_u16le()?; | |
879 | let _packed_size = br.read_u32le()?; | |
880 | let _unpacked_size = br.read_u32le()?; | |
881 | let flags = br.read_byte()?; | |
882 | br.read_skip(3)?; | |
883 | if (flags & 8) != 0 { | |
884 | for i in 0..256 { | |
885 | for j in i..256 { | |
886 | let val = br.read_byte()?; | |
887 | self.filter[i][j] = val; | |
888 | self.filter[j][i] = val; | |
889 | } | |
890 | } | |
891 | } | |
892 | ||
893 | w = (w + 7) & !7; | |
894 | h = (h + 7) & !7; | |
895 | std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2); | |
896 | ||
897 | validate!(x >= 0 && y >= 0); | |
898 | let x = x as usize; | |
899 | let y = y as usize; | |
900 | validate!((x + w <= self.pic.width) && (y + h <= self.pic.height)); | |
901 | ||
902 | let stride = self.pic.width; | |
903 | let dst = &mut self.pic.frm0[x + y * stride..]; | |
904 | match compr { | |
905 | 0 => { | |
906 | for line in dst.chunks_mut(stride).take(h) { | |
907 | br.read_buf(&mut line[..w])?; | |
908 | } | |
909 | }, | |
910 | 2 => { | |
911 | Self::decode_rle(br, dst, w, h, stride)?; | |
912 | }, | |
913 | 3 => { | |
914 | let mut block = [0; 16]; | |
915 | for (row_no, row) in dst.chunks_mut(stride * 8).take((h + 7) / 8).enumerate() { | |
916 | for col in (0..w).step_by(8) { | |
917 | let op = br.read_byte()?; | |
918 | match op { | |
919 | 0xFF => { | |
920 | let val = br.read_byte()?; | |
921 | ||
922 | // it should be interpolated which means reading top pixels... | |
923 | for el in block.iter_mut() { | |
924 | *el = val; | |
925 | } | |
926 | scale2x(&block, &mut row[col..], stride); | |
927 | }, | |
928 | 0xFE => { | |
929 | c48_mv!(offset; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, w, stride, 8); | |
930 | }, | |
931 | 0xFD => { | |
932 | block[ 5] = br.read_byte()?; | |
933 | block[ 7] = br.read_byte()?; | |
934 | block[13] = br.read_byte()?; | |
935 | block[15] = br.read_byte()?; | |
936 | ||
937 | // it should be interpolated which means reading top pixels... | |
938 | block[ 0] = block[ 5]; | |
939 | block[ 1] = block[ 5]; | |
940 | block[ 4] = block[ 5]; | |
941 | block[ 2] = block[ 7]; | |
942 | block[ 3] = block[ 7]; | |
943 | block[ 6] = block[ 7]; | |
944 | block[ 8] = block[13]; | |
945 | block[ 9] = block[13]; | |
946 | block[12] = block[13]; | |
947 | block[10] = block[15]; | |
948 | block[11] = block[15]; | |
949 | block[14] = block[15]; | |
950 | scale2x(&block, &mut row[col..], stride); | |
951 | }, | |
952 | 0xFC => { | |
953 | c48_mv!(index; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, stride, 4, mvsel); | |
954 | }, | |
955 | 0xFB => { | |
956 | c48_mv!(offset; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, w, stride, 4); | |
957 | }, | |
958 | 0xFA => { | |
959 | br.read_buf(&mut block)?; | |
960 | scale2x(&block, &mut row[col..], stride); | |
961 | }, | |
962 | 0xF9 => { | |
963 | c48_mv!(index; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, stride, 2, mvsel); | |
964 | }, | |
965 | 0xF8 => { | |
966 | c48_mv!(offset; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, w, stride, 2); | |
967 | }, | |
968 | 0xF7 => { | |
969 | for line in row[col..].chunks_mut(stride) { | |
970 | br.read_buf(&mut line[..8])?; | |
971 | } | |
972 | }, | |
973 | _ => { | |
974 | br.seek(SeekFrom::Current(-1))?; | |
975 | c48_mv!(index; &mut row[col..], &self.pic.frm2, br, col, row_no * 8, stride, 8, mvsel); | |
976 | }, | |
977 | }; | |
978 | } | |
979 | } | |
980 | }, | |
981 | 5 => { | |
982 | for row in dst.chunks_mut(stride * 2).take((h + 1) / 2) { | |
983 | let mut last = br.read_byte()?; | |
984 | row[0] = last; | |
985 | for col in (1..w).step_by(2) { | |
986 | let new = br.read_byte()?; | |
987 | row[col] = self.filter[last as usize][new as usize]; | |
988 | row[col + 1] = new; | |
989 | last = new; | |
990 | } | |
991 | } | |
992 | let mut off0 = 0; | |
993 | let mut off1 = stride; | |
994 | let mut off2 = stride * 2; | |
995 | for _ in (1..h).step_by(2) { | |
996 | for i in 0..w { | |
997 | dst[off1 + i] = self.filter[dst[off0 + i] as usize][dst[off2 + i] as usize]; | |
998 | } | |
999 | off0 = off2; | |
1000 | off1 += stride * 2; | |
1001 | off2 += stride * 2; | |
1002 | } | |
1003 | }, | |
1004 | _ => return Err(DecoderError::InvalidData), | |
1005 | }; | |
1006 | Ok(()) | |
1007 | } | |
1008 | } | |
1009 | ||
1010 | impl NADecoder for Smush1Decoder { | |
1011 | fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> { | |
1012 | if let Some(edata) = info.get_extradata() { | |
1013 | validate!(!edata.is_empty() && edata[0] <= 2); | |
1014 | self.version = edata[0]; | |
1015 | } | |
1016 | self.pic.init(info) | |
1017 | } | |
1018 | fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> { | |
1019 | let src = pkt.get_buffer(); | |
1020 | validate!(src.len() > 8); | |
1021 | ||
1022 | let mut mr = MemoryReader::new_read(&src); | |
1023 | let mut br = ByteReader::new(&mut mr); | |
1024 | ||
1025 | let mut store = false; | |
1026 | while br.left() > 0 { | |
1027 | let tag = br.read_tag()?; | |
1028 | let size = br.read_u32be()? as usize; | |
1029 | validate!((size as i64) <= br.left()); | |
1030 | match &tag { | |
1031 | b"NPAL" => { | |
1032 | validate!((size % 3) == 0); | |
1033 | br.read_buf(&mut self.pic.pal[..size])?; | |
1034 | }, | |
1035 | b"XPAL" => { | |
1036 | let cmd = br.read_u32be()?; | |
1037 | match cmd { | |
1038 | 0 => { | |
1039 | validate!(size == 0x604); | |
1040 | for el in self.pic.pdelta.iter_mut() { | |
1041 | *el = br.read_u16le()?; | |
1042 | } | |
1043 | for (dst, &src) in self.pic.fpal.iter_mut().zip(self.pic.pal.iter()) { | |
1044 | *dst = u16::from(src) << 7; | |
1045 | } | |
1046 | }, | |
1047 | 1 => { | |
1048 | validate!(size == 4 || size == 6); | |
1049 | for i in 0..768 { | |
1050 | self.pic.fpal[i] = self.pic.fpal[i].wrapping_add(self.pic.pdelta[i]); | |
1051 | self.pic.pal[i] = (self.pic.fpal[i] >> 7) as u8; | |
1052 | } | |
e6aaad5c | 1053 | br.read_skip(size - 4)?; |
c17769db KS |
1054 | }, |
1055 | 2 => { | |
1056 | validate!(size == 0x904); | |
1057 | for el in self.pic.pdelta.iter_mut() { | |
1058 | *el = br.read_u16le()?; | |
1059 | } | |
1060 | br.read_buf(&mut self.pic.pal)?; | |
1061 | }, | |
1062 | _ => return Err(DecoderError::InvalidData), | |
1063 | }; | |
1064 | }, | |
1065 | b"FTCH" => { | |
1066 | br.read_skip(size)?; | |
1067 | self.pic.frm0.copy_from_slice(&self.pic.frm1); | |
1068 | }, | |
1069 | b"STOR" => { | |
1070 | store = true; | |
1071 | br.read_skip(size)?; | |
1072 | }, | |
1073 | b"FOBJ" => { | |
1074 | validate!(size >= 14); | |
1075 | let end = br.tell() + (size as u64); | |
1076 | let compression = br.read_byte()?; | |
1077 | let cparam = br.read_byte()?; | |
1078 | let x = br.read_u16le()? as i16; | |
1079 | let y = br.read_u16le()? as i16; | |
1080 | let w = br.read_u16le()? as usize; | |
1081 | let h = br.read_u16le()? as usize; | |
1082 | let _ = br.read_u16le()?; | |
1083 | let param2 = br.read_u16le()?; | |
1084 | ||
1085 | match compression { | |
1086 | 1 | 3 => self.decode_1(&mut br, x, y, w, h, (compression == 1) ^ (self.version != 1))?, | |
1087 | 2 => self.decode_2(&mut br, x, y, w, h, size - 14)?, | |
1088 | 4 | 33 => self.decode_4(&mut br, x, y, w, h, cparam, param2)?, | |
1089 | 5 | 34 => self.decode_5(&mut br, x, y, w, h, cparam, param2)?, | |
1090 | 21 | 44 => self.decode_21(&mut br, x, y, w, h, size - 14)?, | |
1091 | 23 => self.decode_23(&mut br, x, y, w, h, cparam, param2, self.version == 1)?, | |
1092 | 37 => { | |
1093 | let start = br.tell() as usize; | |
1094 | let end = start + size - 14; | |
1095 | let mut mr = MemoryReader::new_read(&src[start..end]); | |
1096 | let mut br = ByteReader::new(&mut mr); | |
1097 | self.decode_37(&mut br, x, y, w, h)?; | |
1098 | }, | |
1099 | 47 => { | |
1100 | let start = br.tell() as usize; | |
1101 | let end = start + size - 14; | |
1102 | let mut mr = MemoryReader::new_read(&src[start..end]); | |
1103 | let mut br = ByteReader::new(&mut mr); | |
1104 | self.decode_47(&mut br, x, y, w, h)?; | |
1105 | }, | |
1106 | 48 => { | |
1107 | let start = br.tell() as usize; | |
1108 | let end = start + size - 14; | |
1109 | let mut mr = MemoryReader::new_read(&src[start..end]); | |
1110 | let mut br = ByteReader::new(&mut mr); | |
1111 | self.decode_48(&mut br, x, y, w, h)?; | |
1112 | }, | |
1113 | _ => return Err(DecoderError::NotImplemented), | |
1114 | }; | |
1115 | validate!(br.tell() <= end); | |
1116 | let tail = end - br.tell(); | |
1117 | br.read_skip(tail as usize)?; | |
1118 | if store { | |
1119 | self.pic.frm1.copy_from_slice(&self.pic.frm0); | |
1120 | store = false; | |
1121 | } | |
1122 | }, | |
1123 | _ => br.read_skip(size)?, | |
1124 | }; | |
1125 | } | |
1126 | ||
1127 | let ret = self.pic.get_frame(pkt); | |
1128 | ||
1129 | if self.reorder == 2 { | |
1130 | std::mem::swap(&mut self.pic.frm1, &mut self.pic.frm2); | |
1131 | } | |
1132 | if self.reorder != 0 { | |
1133 | std::mem::swap(&mut self.pic.frm0, &mut self.pic.frm2); | |
1134 | } | |
1135 | self.reorder = 0; | |
1136 | ||
1137 | ret | |
1138 | } | |
1139 | fn flush(&mut self) { | |
1140 | } | |
1141 | } | |
1142 | ||
1143 | impl NAOptionHandler for Smush1Decoder { | |
1144 | fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] } | |
1145 | fn set_options(&mut self, _options: &[NAOption]) { } | |
1146 | fn query_option_value(&self, _name: &str) -> Option<NAValue> { None } | |
1147 | } | |
1148 | ||
1149 | ||
1150 | pub fn get_decoder_video_v1() -> Box<dyn NADecoder + Send> { | |
1151 | Box::new(Smush1Decoder::new()) | |
1152 | } | |
1153 | ||
1154 | #[cfg(test)] | |
1155 | mod test { | |
1156 | use nihav_core::codecs::RegisteredDecoders; | |
1157 | use nihav_core::demuxers::RegisteredDemuxers; | |
1158 | use nihav_codec_support::test::dec_video::*; | |
1159 | use crate::game_register_all_decoders; | |
1160 | use crate::game_register_all_demuxers; | |
1161 | // samples from Rebel Assault | |
1162 | #[test] | |
1163 | fn test_smush_anim_v1() { | |
1164 | let mut dmx_reg = RegisteredDemuxers::new(); | |
1165 | game_register_all_demuxers(&mut dmx_reg); | |
1166 | let mut dec_reg = RegisteredDecoders::new(); | |
1167 | game_register_all_decoders(&mut dec_reg); | |
1168 | ||
1169 | test_decoding("smush", "smushv1", "assets/Game/smush/c1block.anm", Some(42), &dmx_reg, &dec_reg, | |
1170 | ExpectedTestResult::MD5([0x39339398, 0x7ce83788, 0xaac917d4, 0xaef9d653])); | |
1171 | test_decoding("smush", "smushv1", "assets/Game/smush/c1c3po.anm", Some(42), &dmx_reg, &dec_reg, | |
1172 | ExpectedTestResult::MD5([0x9c1c2422, 0x2121aa7a, 0xc06418bc, 0xd82d704b])); | |
1173 | test_decoding("smush", "smushv1", "assets/Game/smush/o1option.anm", Some(4), &dmx_reg, &dec_reg, | |
1174 | ExpectedTestResult::MD5([0x21ea3ee9, 0x3d88bcee, 0x9b71a87a, 0xc5e0a006])); | |
1175 | } | |
1176 | #[test] | |
1177 | fn test_smush_anim_v2() { | |
1178 | let mut dmx_reg = RegisteredDemuxers::new(); | |
1179 | game_register_all_demuxers(&mut dmx_reg); | |
1180 | let mut dec_reg = RegisteredDecoders::new(); | |
1181 | game_register_all_decoders(&mut dec_reg); | |
1182 | ||
1183 | // sample from The Dig | |
1184 | test_decoding("smush", "smushv1", "assets/Game/smush/PIGOUT.SAN", Some(42), &dmx_reg, &dec_reg, | |
1185 | ExpectedTestResult::MD5([0x74794559, 0x78a1e484, 0x379a1eec, 0x0609e0b2])); | |
1186 | // sample from Full Throttle | |
1187 | test_decoding("smush", "smushv1", "assets/Game/smush/FIRE.SAN", Some(16), &dmx_reg, &dec_reg, | |
1188 | ExpectedTestResult::MD5([0x442f73b9, 0x0b98d80f, 0xee2f0e19, 0xa555a33d])); | |
1189 | // sample from Mortimer and the Riddles of the Medallion | |
1190 | test_decoding("smush", "smushv1", "assets/Game/smush/FOREST1.SAN", Some(24), &dmx_reg, &dec_reg, | |
1191 | ExpectedTestResult::MD5([0xd5b71505, 0x0ffe79dd, 0xc274dbaf, 0x8b952271])); | |
1192 | // sample from Curse of Monkey Island | |
1193 | test_decoding("smush", "smushv1", "assets/Game/smush/ZAP010.SAN", None, &dmx_reg, &dec_reg, | |
1194 | ExpectedTestResult::MD5([0x369839f1, 0x2daab242, 0x23995d80, 0x501fbe09])); | |
1195 | // sample from Jedi Knight: Mysteries of the Sith | |
1196 | test_decoding("smush", "smushv1", "assets/Game/smush/S2L4ECS.SAN", Some(42), &dmx_reg, &dec_reg, | |
1197 | ExpectedTestResult::MD5([0x4525b5f3, 0x9fe5fb23, 0xf5f27980, 0x12589ce1])); | |
1198 | } | |
1199 | } | |
1200 | ||
1201 | const C37_MV: [[i8; 255 * 2]; 3] = [ | |
1202 | [ | |
1203 | 0, 0, 1, 0, 2, 0, 3, 0, 5, 0, 8, 0, 13, 0, 21, | |
1204 | 0, -1, 0, -2, 0, -3, 0, -5, 0, -8, 0, -13, 0, -17, 0, | |
1205 | -21, 0, 0, 1, 1, 1, 2, 1, 3, 1, 5, 1, 8, 1, 13, | |
1206 | 1, 21, 1, -1, 1, -2, 1, -3, 1, -5, 1, -8, 1, -13, 1, | |
1207 | -17, 1, -21, 1, 0, 2, 1, 2, 2, 2, 3, 2, 5, 2, 8, | |
1208 | 2, 13, 2, 21, 2, -1, 2, -2, 2, -3, 2, -5, 2, -8, 2, | |
1209 | -13, 2, -17, 2, -21, 2, 0, 3, 1, 3, 2, 3, 3, 3, 5, | |
1210 | 3, 8, 3, 13, 3, 21, 3, -1, 3, -2, 3, -3, 3, -5, 3, | |
1211 | -8, 3, -13, 3, -17, 3, -21, 3, 0, 5, 1, 5, 2, 5, 3, | |
1212 | 5, 5, 5, 8, 5, 13, 5, 21, 5, -1, 5, -2, 5, -3, 5, | |
1213 | -5, 5, -8, 5, -13, 5, -17, 5, -21, 5, 0, 8, 1, 8, 2, | |
1214 | 8, 3, 8, 5, 8, 8, 8, 13, 8, 21, 8, -1, 8, -2, 8, | |
1215 | -3, 8, -5, 8, -8, 8, -13, 8, -17, 8, -21, 8, 0, 13, 1, | |
1216 | 13, 2, 13, 3, 13, 5, 13, 8, 13, 13, 13, 21, 13, -1, 13, | |
1217 | -2, 13, -3, 13, -5, 13, -8, 13, -13, 13, -17, 13, -21, 13, 0, | |
1218 | 21, 1, 21, 2, 21, 3, 21, 5, 21, 8, 21, 13, 21, 21, 21, | |
1219 | -1, 21, -2, 21, -3, 21, -5, 21, -8, 21, -13, 21, -17, 21, -21, | |
1220 | 21, 0, -1, 1, -1, 2, -1, 3, -1, 5, -1, 8, -1, 13, -1, | |
1221 | 21, -1, -1, -1, -2, -1, -3, -1, -5, -1, -8, -1, -13, -1, -17, | |
1222 | -1, -21, -1, 0, -2, 1, -2, 2, -2, 3, -2, 5, -2, 8, -2, | |
1223 | 13, -2, 21, -2, -1, -2, -2, -2, -3, -2, -5, -2, -8, -2, -13, | |
1224 | -2, -17, -2, -21, -2, 0, -3, 1, -3, 2, -3, 3, -3, 5, -3, | |
1225 | 8, -3, 13, -3, 21, -3, -1, -3, -2, -3, -3, -3, -5, -3, -8, | |
1226 | -3, -13, -3, -17, -3, -21, -3, 0, -5, 1, -5, 2, -5, 3, -5, | |
1227 | 5, -5, 8, -5, 13, -5, 21, -5, -1, -5, -2, -5, -3, -5, -5, | |
1228 | -5, -8, -5, -13, -5, -17, -5, -21, -5, 0, -8, 1, -8, 2, -8, | |
1229 | 3, -8, 5, -8, 8, -8, 13, -8, 21, -8, -1, -8, -2, -8, -3, | |
1230 | -8, -5, -8, -8, -8, -13, -8, -17, -8, -21, -8, 0, -13, 1, -13, | |
1231 | 2, -13, 3, -13, 5, -13, 8, -13, 13, -13, 21, -13, -1, -13, -2, | |
1232 | -13, -3, -13, -5, -13, -8, -13, -13, -13, -17, -13, -21, -13, 0, -17, | |
1233 | 1, -17, 2, -17, 3, -17, 5, -17, 8, -17, 13, -17, 21, -17, -1, | |
1234 | -17, -2, -17, -3, -17, -5, -17, -8, -17, -13, -17, -17, -17, -21, -17, | |
1235 | 0, -21, 1, -21, 2, -21, 3, -21, 5, -21, 8, -21, 13, -21, 21, | |
1236 | -21, -1, -21, -2, -21, -3, -21, -5, -21, -8, -21, -13, -21, -17, -21 | |
1237 | ], [ | |
1238 | 0, 0, -8, -29, 8, -29, -18, -25, 17, -25, 0, -23, -6, -22, 6, | |
1239 | -22, -13, -19, 12, -19, 0, -18, 25, -18, -25, -17, -5, -17, 5, -17, | |
1240 | -10, -15, 10, -15, 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, -8, | |
1241 | -11, -2, -11, 0, -11, 2, -11, 8, -11, -15, -10, -4, -10, 4, -10, | |
1242 | 15, -10, -6, -9, -1, -9, 1, -9, 6, -9, -29, -8, -11, -8, -8, | |
1243 | -8, -3, -8, 3, -8, 8, -8, 11, -8, 29, -8, -5, -7, -2, -7, | |
1244 | 0, -7, 2, -7, 5, -7, -22, -6, -9, -6, -6, -6, -3, -6, -1, | |
1245 | -6, 1, -6, 3, -6, 6, -6, 9, -6, 22, -6, -17, -5, -7, -5, | |
1246 | -4, -5, -2, -5, 0, -5, 2, -5, 4, -5, 7, -5, 17, -5, -13, | |
1247 | -4, -10, -4, -5, -4, -3, -4, -1, -4, 0, -4, 1, -4, 3, -4, | |
1248 | 5, -4, 10, -4, 13, -4, -8, -3, -6, -3, -4, -3, -3, -3, -2, | |
1249 | -3, -1, -3, 0, -3, 1, -3, 2, -3, 4, -3, 6, -3, 8, -3, | |
1250 | -11, -2, -7, -2, -5, -2, -3, -2, -2, -2, -1, -2, 0, -2, 1, | |
1251 | -2, 2, -2, 3, -2, 5, -2, 7, -2, 11, -2, -9, -1, -6, -1, | |
1252 | -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, | |
1253 | -1, 4, -1, 6, -1, 9, -1, -31, 0, -23, 0, -18, 0, -14, 0, | |
1254 | -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 0, | |
1255 | -31, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, | |
1256 | 14, 0, 18, 0, 23, 0, 31, 0, -9, 1, -6, 1, -4, 1, -3, | |
1257 | 1, -2, 1, -1, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, | |
1258 | 6, 1, 9, 1, -11, 2, -7, 2, -5, 2, -3, 2, -2, 2, -1, | |
1259 | 2, 0, 2, 1, 2, 2, 2, 3, 2, 5, 2, 7, 2, 11, 2, | |
1260 | -8, 3, -6, 3, -4, 3, -2, 3, -1, 3, 0, 3, 1, 3, 2, | |
1261 | 3, 3, 3, 4, 3, 6, 3, 8, 3, -13, 4, -10, 4, -5, 4, | |
1262 | -3, 4, -1, 4, 0, 4, 1, 4, 3, 4, 5, 4, 10, 4, 13, | |
1263 | 4, -17, 5, -7, 5, -4, 5, -2, 5, 0, 5, 2, 5, 4, 5, | |
1264 | 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, -3, 6, -1, 6, 1, | |
1265 | 6, 3, 6, 6, 6, 9, 6, 22, 6, -5, 7, -2, 7, 0, 7, | |
1266 | 2, 7, 5, 7, -29, 8, -11, 8, -8, 8, -3, 8, 3, 8, 8, | |
1267 | 8, 11, 8, 29, 8, -6, 9, -1, 9, 1, 9, 6, 9, -15, 10, | |
1268 | -4, 10, 4, 10, 15, 10, -8, 11, -2, 11, 0, 11, 2, 11, 8, | |
1269 | 11, 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, | |
1270 | -5, 17, 5, 17, 25, 17, -25, 18, 0, 18, -12, 19, 13, 19, -6, | |
1271 | 22, 6, 22, 0, 23, -17, 25, 18, 25, -8, 29, 8, 29, 0, 31 | |
1272 | ], [ | |
1273 | 0, 0, -6, -22, 6, -22, -13, -19, 12, -19, 0, -18, -5, -17, 5, | |
1274 | -17, -10, -15, 10, -15, 0, -14, -4, -13, 4, -13, 19, -13, -19, -12, | |
1275 | -8, -11, -2, -11, 0, -11, 2, -11, 8, -11, -15, -10, -4, -10, 4, | |
1276 | -10, 15, -10, -6, -9, -1, -9, 1, -9, 6, -9, -11, -8, -8, -8, | |
1277 | -3, -8, 0, -8, 3, -8, 8, -8, 11, -8, -5, -7, -2, -7, 0, | |
1278 | -7, 2, -7, 5, -7, -22, -6, -9, -6, -6, -6, -3, -6, -1, -6, | |
1279 | 1, -6, 3, -6, 6, -6, 9, -6, 22, -6, -17, -5, -7, -5, -4, | |
1280 | -5, -2, -5, -1, -5, 0, -5, 1, -5, 2, -5, 4, -5, 7, -5, | |
1281 | 17, -5, -13, -4, -10, -4, -5, -4, -3, -4, -2, -4, -1, -4, 0, | |
1282 | -4, 1, -4, 2, -4, 3, -4, 5, -4, 10, -4, 13, -4, -8, -3, | |
1283 | -6, -3, -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, 1, -3, 2, | |
1284 | -3, 3, -3, 4, -3, 6, -3, 8, -3, -11, -2, -7, -2, -5, -2, | |
1285 | -4, -2, -3, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 3, | |
1286 | -2, 4, -2, 5, -2, 7, -2, 11, -2, -9, -1, -6, -1, -5, -1, | |
1287 | -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, | |
1288 | -1, 4, -1, 5, -1, 6, -1, 9, -1, -23, 0, -18, 0, -14, 0, | |
1289 | -11, 0, -7, 0, -5, 0, -4, 0, -3, 0, -2, 0, -1, 0, 0, | |
1290 | -23, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 7, 0, 11, 0, | |
1291 | 14, 0, 18, 0, 23, 0, -9, 1, -6, 1, -5, 1, -4, 1, -3, | |
1292 | 1, -2, 1, -1, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, | |
1293 | 5, 1, 6, 1, 9, 1, -11, 2, -7, 2, -5, 2, -4, 2, -3, | |
1294 | 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2, 3, 2, 4, 2, | |
1295 | 5, 2, 7, 2, 11, 2, -8, 3, -6, 3, -4, 3, -3, 3, -2, | |
1296 | 3, -1, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, 3, 6, 3, | |
1297 | 8, 3, -13, 4, -10, 4, -5, 4, -3, 4, -2, 4, -1, 4, 0, | |
1298 | 4, 1, 4, 2, 4, 3, 4, 5, 4, 10, 4, 13, 4, -17, 5, | |
1299 | -7, 5, -4, 5, -2, 5, -1, 5, 0, 5, 1, 5, 2, 5, 4, | |
1300 | 5, 7, 5, 17, 5, -22, 6, -9, 6, -6, 6, -3, 6, -1, 6, | |
1301 | 1, 6, 3, 6, 6, 6, 9, 6, 22, 6, -5, 7, -2, 7, 0, | |
1302 | 7, 2, 7, 5, 7, -11, 8, -8, 8, -3, 8, 0, 8, 3, 8, | |
1303 | 8, 8, 11, 8, -6, 9, -1, 9, 1, 9, 6, 9, -15, 10, -4, | |
1304 | 10, 4, 10, 15, 10, -8, 11, -2, 11, 0, 11, 2, 11, 8, 11, | |
1305 | 19, 12, -19, 13, -4, 13, 4, 13, 0, 14, -10, 15, 10, 15, -5, | |
1306 | 17, 5, 17, 0, 18, -12, 19, 13, 19, -6, 22, 6, 22, 0, 23 | |
1307 | ] | |
1308 | ]; | |
1309 | ||
1310 | const C47_MV: [[[i8; 2]; 255]; 2] = [ | |
1311 | [ | |
1312 | [ 0, 0], [ -1, -43], [ 6, -43], [ -9, -42], [ 13, -41], | |
1313 | [-16, -40], [ 19, -39], [-23, -36], [ 26, -34], [ -2, -33], | |
1314 | [ 4, -33], [-29, -32], [ -9, -32], [ 11, -31], [-16, -29], | |
1315 | [ 32, -29], [ 18, -28], [-34, -26], [-22, -25], [ -1, -25], | |
1316 | [ 3, -25], [ -7, -24], [ 8, -24], [ 24, -23], [ 36, -23], | |
1317 | [-12, -22], [ 13, -21], [-38, -20], [ 0, -20], [-27, -19], | |
1318 | [ -4, -19], [ 4, -19], [-17, -18], [ -8, -17], [ 8, -17], | |
1319 | [ 18, -17], [ 28, -17], [ 39, -17], [-12, -15], [ 12, -15], | |
1320 | [-21, -14], [ -1, -14], [ 1, -14], [-41, -13], [ -5, -13], | |
1321 | [ 5, -13], [ 21, -13], [-31, -12], [-15, -11], [ -8, -11], | |
1322 | [ 8, -11], [ 15, -11], [ -2, -10], [ 1, -10], [ 31, -10], | |
1323 | [-23, -9], [-11, -9], [ -5, -9], [ 4, -9], [ 11, -9], | |
1324 | [ 42, -9], [ 6, -8], [ 24, -8], [-18, -7], [ -7, -7], | |
1325 | [ -3, -7], [ -1, -7], [ 2, -7], [ 18, -7], [-43, -6], | |
1326 | [-13, -6], [ -4, -6], [ 4, -6], [ 8, -6], [-33, -5], | |
1327 | [ -9, -5], [ -2, -5], [ 0, -5], [ 2, -5], [ 5, -5], | |
1328 | [ 13, -5], [-25, -4], [ -6, -4], [ -3, -4], [ 3, -4], | |
1329 | [ 9, -4], [-19, -3], [ -7, -3], [ -4, -3], [ -2, -3], | |
1330 | [ -1, -3], [ 0, -3], [ 1, -3], [ 2, -3], [ 4, -3], | |
1331 | [ 6, -3], [ 33, -3], [-14, -2], [-10, -2], [ -5, -2], | |
1332 | [ -3, -2], [ -2, -2], [ -1, -2], [ 0, -2], [ 1, -2], | |
1333 | [ 2, -2], [ 3, -2], [ 5, -2], [ 7, -2], [ 14, -2], | |
1334 | [ 19, -2], [ 25, -2], [ 43, -2], [ -7, -1], [ -3, -1], | |
1335 | [ -2, -1], [ -1, -1], [ 0, -1], [ 1, -1], [ 2, -1], | |
1336 | [ 3, -1], [ 10, -1], [ -5, 0], [ -3, 0], [ -2, 0], | |
1337 | [ -1, 0], [ 1, 0], [ 2, 0], [ 3, 0], [ 5, 0], | |
1338 | [ 7, 0], [-10, 1], [ -7, 1], [ -3, 1], [ -2, 1], | |
1339 | [ -1, 1], [ 0, 1], [ 1, 1], [ 2, 1], [ 3, 1], | |
1340 | [-43, 2], [-25, 2], [-19, 2], [-14, 2], [ -5, 2], | |
1341 | [ -3, 2], [ -2, 2], [ -1, 2], [ 0, 2], [ 1, 2], | |
1342 | [ 2, 2], [ 3, 2], [ 5, 2], [ 7, 2], [ 10, 2], | |
1343 | [ 14, 2], [-33, 3], [ -6, 3], [ -4, 3], [ -2, 3], | |
1344 | [ -1, 3], [ 0, 3], [ 1, 3], [ 2, 3], [ 4, 3], | |
1345 | [ 19, 3], [ -9, 4], [ -3, 4], [ 3, 4], [ 7, 4], | |
1346 | [ 25, 4], [-13, 5], [ -5, 5], [ -2, 5], [ 0, 5], | |
1347 | [ 2, 5], [ 5, 5], [ 9, 5], [ 33, 5], [ -8, 6], | |
1348 | [ -4, 6], [ 4, 6], [ 13, 6], [ 43, 6], [-18, 7], | |
1349 | [ -2, 7], [ 0, 7], [ 2, 7], [ 7, 7], [ 18, 7], | |
1350 | [-24, 8], [ -6, 8], [-42, 9], [-11, 9], [ -4, 9], | |
1351 | [ 5, 9], [ 11, 9], [ 23, 9], [-31, 10], [ -1, 10], | |
1352 | [ 2, 10], [-15, 11], [ -8, 11], [ 8, 11], [ 15, 11], | |
1353 | [ 31, 12], [-21, 13], [ -5, 13], [ 5, 13], [ 41, 13], | |
1354 | [ -1, 14], [ 1, 14], [ 21, 14], [-12, 15], [ 12, 15], | |
1355 | [-39, 17], [-28, 17], [-18, 17], [ -8, 17], [ 8, 17], | |
1356 | [ 17, 18], [ -4, 19], [ 0, 19], [ 4, 19], [ 27, 19], | |
1357 | [ 38, 20], [-13, 21], [ 12, 22], [-36, 23], [-24, 23], | |
1358 | [ -8, 24], [ 7, 24], [ -3, 25], [ 1, 25], [ 22, 25], | |
1359 | [ 34, 26], [-18, 28], [-32, 29], [ 16, 29], [-11, 31], | |
1360 | [ 9, 32], [ 29, 32], [ -4, 33], [ 2, 33], [-26, 34], | |
1361 | [ 23, 36], [-19, 39], [ 16, 40], [-13, 41], [ 9, 42], | |
1362 | [ -6, 43], [ 1, 43], [ 0, 0], [ 0, 0], [ 0, 0], | |
1363 | ], [ | |
1364 | [ 0, 0], [ 1, 0], [ 2, 0], [ 3, 0], [ 5, 0], | |
1365 | [ 8, 0], [ 13, 0], [ 21, 0], [ -1, 0], [ -2, 0], | |
1366 | [ -3, 0], [ -5, 0], [ -8, 0], [-13, 0], [-17, 0], | |
1367 | [-21, 0], [ 0, 1], [ 1, 1], [ 2, 1], [ 3, 1], | |
1368 | [ 5, 1], [ 8, 1], [ 13, 1], [ 21, 1], [ -1, 1], | |
1369 | [ -2, 1], [ -3, 1], [ -5, 1], [ -8, 1], [-13, 1], | |
1370 | [-17, 1], [-21, 1], [ 0, 2], [ 1, 2], [ 2, 2], | |
1371 | [ 3, 2], [ 5, 2], [ 8, 2], [ 13, 2], [ 21, 2], | |
1372 | [ -1, 2], [ -2, 2], [ -3, 2], [ -5, 2], [ -8, 2], | |
1373 | [-13, 2], [-17, 2], [-21, 2], [ 0, 3], [ 1, 3], | |
1374 | [ 2, 3], [ 3, 3], [ 5, 3], [ 8, 3], [ 13, 3], | |
1375 | [ 21, 3], [ -1, 3], [ -2, 3], [ -3, 3], [ -5, 3], | |
1376 | [ -8, 3], [-13, 3], [-17, 3], [-21, 3], [ 0, 5], | |
1377 | [ 1, 5], [ 2, 5], [ 3, 5], [ 5, 5], [ 8, 5], | |
1378 | [ 13, 5], [ 21, 5], [ -1, 5], [ -2, 5], [ -3, 5], | |
1379 | [ -5, 5], [ -8, 5], [-13, 5], [-17, 5], [-21, 5], | |
1380 | [ 0, 8], [ 1, 8], [ 2, 8], [ 3, 8], [ 5, 8], | |
1381 | [ 8, 8], [ 13, 8], [ 21, 8], [ -1, 8], [ -2, 8], | |
1382 | [ -3, 8], [ -5, 8], [ -8, 8], [-13, 8], [-17, 8], | |
1383 | [-21, 8], [ 0, 13], [ 1, 13], [ 2, 13], [ 3, 13], | |
1384 | [ 5, 13], [ 8, 13], [ 13, 13], [ 21, 13], [ -1, 13], | |
1385 | [ -2, 13], [ -3, 13], [ -5, 13], [ -8, 13], [-13, 13], | |
1386 | [-17, 13], [-21, 13], [ 0, 21], [ 1, 21], [ 2, 21], | |
1387 | [ 3, 21], [ 5, 21], [ 8, 21], [ 13, 21], [ 21, 21], | |
1388 | [ -1, 21], [ -2, 21], [ -3, 21], [ -5, 21], [ -8, 21], | |
1389 | [-13, 21], [-17, 21], [-21, 21], [ 0, -1], [ 1, -1], | |
1390 | [ 2, -1], [ 3, -1], [ 5, -1], [ 8, -1], [ 13, -1], | |
1391 | [ 21, -1], [ -1, -1], [ -2, -1], [ -3, -1], [ -5, -1], | |
1392 | [ -8, -1], [-13, -1], [-17, -1], [-21, -1], [ 0, -2], | |
1393 | [ 1, -2], [ 2, -2], [ 3, -2], [ 5, -2], [ 8, -2], | |
1394 | [ 13, -2], [ 21, -2], [ -1, -2], [ -2, -2], [ -3, -2], | |
1395 | [ -5, -2], [ -8, -2], [-13, -2], [-17, -2], [-21, -2], | |
1396 | [ 0, -3], [ 1, -3], [ 2, -3], [ 3, -3], [ 5, -3], | |
1397 | [ 8, -3], [ 13, -3], [ 21, -3], [ -1, -3], [ -2, -3], | |
1398 | [ -3, -3], [ -5, -3], [ -8, -3], [-13, -3], [-17, -3], | |
1399 | [-21, -3], [ 0, -5], [ 1, -5], [ 2, -5], [ 3, -5], | |
1400 | [ 5, -5], [ 8, -5], [ 13, -5], [ 21, -5], [ -1, -5], | |
1401 | [ -2, -5], [ -3, -5], [ -5, -5], [ -8, -5], [-13, -5], | |
1402 | [-17, -5], [-21, -5], [ 0, -8], [ 1, -8], [ 2, -8], | |
1403 | [ 3, -8], [ 5, -8], [ 8, -8], [ 13, -8], [ 21, -8], | |
1404 | [ -1, -8], [ -2, -8], [ -3, -8], [ -5, -8], [ -8, -8], | |
1405 | [-13, -8], [-17, -8], [-21, -8], [ 0, -13], [ 1, -13], | |
1406 | [ 2, -13], [ 3, -13], [ 5, -13], [ 8, -13], [ 13, -13], | |
1407 | [ 21, -13], [ -1, -13], [ -2, -13], [ -3, -13], [ -5, -13], | |
1408 | [ -8, -13], [-13, -13], [-17, -13], [-21, -13], [ 0, -17], | |
1409 | [ 1, -17], [ 2, -17], [ 3, -17], [ 5, -17], [ 8, -17], | |
1410 | [ 13, -17], [ 21, -17], [ -1, -17], [ -2, -17], [ -3, -17], | |
1411 | [ -5, -17], [ -8, -17], [-13, -17], [-17, -17], [-21, -17], | |
1412 | [ 0, -21], [ 1, -21], [ 2, -21], [ 3, -21], [ 5, -21], | |
1413 | [ 8, -21], [ 13, -21], [ 21, -21], [ -1, -21], [ -2, -21], | |
1414 | [ -3, -21], [ -5, -21], [ -8, -21], [-13, -21], [-17, -21] | |
1415 | ] | |
1416 | ]; |