add LinePack decoder
[nihav.git] / nihav-game / src / codecs / sga.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3
4 const RGB555_FORMAT: NAPixelFormaton = NAPixelFormaton { model: ColorModel::RGB(RGBSubmodel::RGB), components: 3,
5 comp_info: [
6 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 10, comp_offs: 0, next_elem: 2 }),
7 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 5, comp_offs: 1, next_elem: 2 }),
8 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 0, comp_offs: 2, next_elem: 2 }),
9 None, None],
10 elem_size: 2, be: false, alpha: false, palette: false };
11
12 const OPCODE_SKIP: usize = 91;
13
14 struct DPVideoDecoder {
15 info: NACodecInfoRef,
16 pal: [u16; 256],
17 subtype: u8,
18 frame: Vec<u8>,
19 width: usize,
20 height: usize,
21 }
22
23 impl DPVideoDecoder {
24 fn new() -> Self {
25 Self {
26 info: NACodecInfoRef::default(),
27 pal: [0; 256],
28 subtype: 0,
29 frame: Vec::new(),
30 width: 0,
31 height: 0,
32 }
33 }
34 fn decode_81(&mut self, br: &mut ByteReader) -> DecoderResult<()> {
35 let mut pat = [0; 8];
36 let mut cur_clr = [0; 16];
37 let mut off = 0;
38 let mut rle_len = 0;
39 let mut src_off = 0;
40 let mut had_skips = false;
41 for _y in (0..self.height).step_by(8) {
42 for x in (0..self.width).step_by(8) {
43 let off = off + x;
44 if rle_len > 0 {
45 copy_block(&mut self.frame, self.width, src_off, off, if had_skips { 15 } else { 0 });
46 rle_len -= 1;
47 continue;
48 }
49
50 let mut op = usize::from(br.read_byte()?);
51 if (op & 0x80) != 0 {
52 rle_len = (op & 0x7F) + 1;
53 op = usize::from(br.read_byte()?);
54 src_off = off;
55 had_skips = false;
56 }
57 validate!(op < 0x80);
58 match OPCODE_TYPE[op] {
59 4 => {
60 if op < OPCODE_SKIP {
61 let nclrs = usize::from(PATTERN_COLOURS[op]);
62 assert_eq!(nclrs, 2);
63 br.read_buf(&mut cur_clr[..nclrs])?;
64 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
65 let psrc = if pattern == 0 {
66 br.read_buf(&mut pat)?;
67 &pat
68 } else {
69 &PATTERN_8X8[pattern]
70 };
71 paint_8x8(&mut self.frame[off..], self.width, psrc, &cur_clr);
72 } else {
73 had_skips = true;
74 }
75 },
76 2 => {
77 if op < OPCODE_SKIP {
78 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
79 let nclrs = usize::from(PATTERN_COLOURS[op]);
80 br.read_buf(&mut cur_clr[..nclrs])?;
81 let mask = br.read_u32le()?;
82 paint_8x4_old(&mut self.frame[off..], self.width, &PATTERN_8X4_OLD[pattern], &cur_clr, mask);
83 }
84 let op = usize::from(br.read_byte()?);
85 validate!(op < 0x80);
86 match OPCODE_TYPE[op] {
87 2 => {
88 if op < OPCODE_SKIP {
89 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
90 let nclrs = usize::from(PATTERN_COLOURS[op]);
91 br.read_buf(&mut cur_clr[..nclrs])?;
92 let mask = br.read_u32le()?;
93 paint_8x4_old(&mut self.frame[off + self.width * 4..], self.width, &PATTERN_8X4_OLD[pattern], &cur_clr, mask);
94 }
95 },
96 0 => {
97 if op < OPCODE_SKIP {
98 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
99 let nclrs = usize::from(PATTERN_COLOURS[op]);
100 br.read_buf(&mut cur_clr[..nclrs])?;
101 let mask = br.read_u16le()?;
102 paint_4x4_old(&mut self.frame[off + self.width * 4..], self.width, &PATTERN_4X4_OLD[pattern], &cur_clr, mask);
103 }
104 let op = usize::from(br.read_byte()?);
105 validate!(op < 0x80 && OPCODE_TYPE[op] == 0);
106 if op < OPCODE_SKIP {
107 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
108 let nclrs = usize::from(PATTERN_COLOURS[op]);
109 br.read_buf(&mut cur_clr[..nclrs])?;
110 let mask = br.read_u16le()?;
111 paint_4x4_old(&mut self.frame[off + self.width * 4 + 4..], self.width, &PATTERN_4X4_OLD[pattern], &cur_clr, mask);
112 }
113 },
114 _ => return Err(DecoderError::InvalidData),
115 };
116 },
117 _ => {
118 if op < OPCODE_SKIP {
119 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
120 let nclrs = usize::from(PATTERN_COLOURS[op]);
121 br.read_buf(&mut cur_clr[..nclrs])?;
122 let mask = br.read_u16le()?;
123 paint_4x4_old(&mut self.frame[off..], self.width, &PATTERN_4X4_OLD[pattern], &cur_clr, mask);
124 }
125 let op = usize::from(br.read_byte()?);
126 validate!(op < 0x80 && OPCODE_TYPE[op] == 0);
127 if op < OPCODE_SKIP {
128 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
129 let nclrs = usize::from(PATTERN_COLOURS[op]);
130 br.read_buf(&mut cur_clr[..nclrs])?;
131 let mask = br.read_u16le()?;
132 paint_4x4_old(&mut self.frame[off + 4..], self.width, &PATTERN_4X4_OLD[pattern], &cur_clr, mask);
133 }
134 let op = usize::from(br.read_byte()?);
135 validate!(op < 0x80);
136 match OPCODE_TYPE[op] {
137 2 => {
138 if op < OPCODE_SKIP {
139 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
140 let nclrs = usize::from(PATTERN_COLOURS[op]);
141 br.read_buf(&mut cur_clr[..nclrs])?;
142 let mask = br.read_u32le()?;
143 paint_8x4_old(&mut self.frame[off + self.width * 4..], self.width, &PATTERN_8X4_OLD[pattern], &cur_clr, mask);
144 }
145 },
146 0 => {
147 if op < OPCODE_SKIP {
148 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
149 let nclrs = usize::from(PATTERN_COLOURS[op]);
150 br.read_buf(&mut cur_clr[..nclrs])?;
151 let mask = br.read_u16le()?;
152 paint_4x4_old(&mut self.frame[off + self.width * 4..], self.width, &PATTERN_4X4_OLD[pattern], &cur_clr, mask);
153 }
154 let op = usize::from(br.read_byte()?);
155 validate!(op < 0x80 && OPCODE_TYPE[op] == 0);
156 if op < OPCODE_SKIP {
157 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
158 let nclrs = usize::from(PATTERN_COLOURS[op]);
159 br.read_buf(&mut cur_clr[..nclrs])?;
160 let mask = br.read_u16le()?;
161 paint_4x4_old(&mut self.frame[off + self.width * 4 + 4..], self.width, &PATTERN_4X4_OLD[pattern], &cur_clr, mask);
162 }
163 },
164 _ => return Err(DecoderError::InvalidData),
165 };
166 },
167 };
168 }
169 off += self.width * 8;
170 }
171 Ok(())
172 }
173 fn decode_85(&mut self, clr_src: &[u8], op_src: &[u8]) -> DecoderResult<()> {
174 let mut mr = MemoryReader::new_read(clr_src);
175 let mut clrs = ByteReader::new(&mut mr);
176 let mut mr = MemoryReader::new_read(op_src);
177 let mut ops = ByteReader::new(&mut mr);
178
179 let mut pat = [0; 8];
180 let mut cur_clr = [0; 16];
181
182 let mut off = 0;
183 let mut rle_len = 0;
184 let mut rle_mode = 0;
185 let mut src_off = 0;
186 for _y in (0..self.height).step_by(8) {
187 for x in (0..self.width).step_by(8) {
188 let off = off + x;
189 if rle_len > 0 {
190 copy_block(&mut self.frame, self.width, src_off, off, rle_mode);
191 rle_len -= 1;
192 continue;
193 }
194 let op = usize::from(ops.read_byte()?);
195 if op < 0x80 {
196 src_off = off;
197 match OPCODE_TYPE[op] {
198 4 => {
199 if op < OPCODE_SKIP {
200 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
201 let psrc = if pattern == 0 {
202 ops.read_buf(&mut pat)?;
203 &pat
204 } else {
205 &PATTERN_8X8[pattern]
206 };
207 let nclrs = usize::from(PATTERN_COLOURS[op]);
208 assert_eq!(nclrs, 2);
209 clrs.read_buf(&mut cur_clr[..nclrs])?;
210 if pattern == 0 {
211 cur_clr.swap(0, 1);
212 }
213 paint_8x8(&mut self.frame[off..], self.width, psrc, &cur_clr);
214 }
215 },
216 2 => {
217 if op < OPCODE_SKIP {
218 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
219 let nclrs = usize::from(PATTERN_COLOURS[op]);
220 clrs.read_buf(&mut cur_clr[..nclrs])?;
221 let mask = ops.read_u32le()?;
222 paint_8x4(&mut self.frame[off..], self.width, &PATTERN_8X4[pattern], &cur_clr, mask);
223 }
224 let op = usize::from(ops.read_byte()?);
225 validate!(op < 0x80);
226 match OPCODE_TYPE[op] {
227 2 => {
228 if op < OPCODE_SKIP {
229 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
230 let nclrs = usize::from(PATTERN_COLOURS[op]);
231 clrs.read_buf(&mut cur_clr[..nclrs])?;
232 let mask = ops.read_u32le()?;
233 paint_8x4(&mut self.frame[off + self.width * 4..], self.width, &PATTERN_8X4[pattern], &cur_clr, mask);
234 }
235 },
236 0 => {
237 if op < OPCODE_SKIP {
238 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
239 let nclrs = usize::from(PATTERN_COLOURS[op]);
240 clrs.read_buf(&mut cur_clr[..nclrs])?;
241 let mask = ops.read_u16le()?;
242 paint_4x4(&mut self.frame[off + self.width * 4..], self.width, &PATTERN_4X4[pattern], &cur_clr, mask);
243 }
244 let op = usize::from(ops.read_byte()?);
245 validate!(op < 0x80 && OPCODE_TYPE[op] == 0);
246 if op < OPCODE_SKIP {
247 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
248 let nclrs = usize::from(PATTERN_COLOURS[op]);
249 clrs.read_buf(&mut cur_clr[..nclrs])?;
250 let mask = ops.read_u16le()?;
251 paint_4x4(&mut self.frame[off + self.width * 4 + 4..], self.width, &PATTERN_4X4[pattern], &cur_clr, mask);
252 }
253 },
254 _ => return Err(DecoderError::InvalidData),
255 };
256 },
257 _ => {
258 if op < OPCODE_SKIP {
259 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
260 let nclrs = usize::from(PATTERN_COLOURS[op]);
261 clrs.read_buf(&mut cur_clr[..nclrs])?;
262 let mask = ops.read_u16le()?;
263 paint_4x4(&mut self.frame[off..], self.width, &PATTERN_4X4[pattern], &cur_clr, mask);
264 }
265 let op = usize::from(ops.read_byte()?);
266 validate!(op < 0x80 && OPCODE_TYPE[op] == 0);
267 if op < OPCODE_SKIP {
268 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
269 let nclrs = usize::from(PATTERN_COLOURS[op]);
270 clrs.read_buf(&mut cur_clr[..nclrs])?;
271 let mask = ops.read_u16le()?;
272 paint_4x4(&mut self.frame[off + 4..], self.width, &PATTERN_4X4[pattern], &cur_clr, mask);
273 }
274 let op = usize::from(ops.read_byte()?);
275 validate!(op < 0x80);
276 match OPCODE_TYPE[op] {
277 2 => {
278 if op < OPCODE_SKIP {
279 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
280 let nclrs = usize::from(PATTERN_COLOURS[op]);
281 clrs.read_buf(&mut cur_clr[..nclrs])?;
282 let mask = ops.read_u32le()?;
283 paint_8x4(&mut self.frame[off + self.width * 4..], self.width, &PATTERN_8X4[pattern], &cur_clr, mask);
284 }
285 },
286 0 => {
287 if op < OPCODE_SKIP {
288 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
289 let nclrs = usize::from(PATTERN_COLOURS[op]);
290 clrs.read_buf(&mut cur_clr[..nclrs])?;
291 let mask = ops.read_u16le()?;
292 paint_4x4(&mut self.frame[off + self.width * 4..], self.width, &PATTERN_4X4[pattern], &cur_clr, mask);
293 }
294 let op = usize::from(ops.read_byte()?);
295 validate!(op < 0x80 && OPCODE_TYPE[op] == 0);
296 if op < OPCODE_SKIP {
297 let pattern = usize::from(OPCODE_TO_PATTERN[op]);
298 let nclrs = usize::from(PATTERN_COLOURS[op]);
299 clrs.read_buf(&mut cur_clr[..nclrs])?;
300 let mask = ops.read_u16le()?;
301 paint_4x4(&mut self.frame[off + self.width * 4 + 4..], self.width, &PATTERN_4X4[pattern], &cur_clr, mask);
302 }
303 },
304 _ => return Err(DecoderError::InvalidData),
305 };
306 },
307 };
308 } else {
309 rle_mode = ((op >> 3) & 0xF) as u8;
310 rle_len = op & 7;
311 if rle_len == 7 {
312 rle_len = usize::from(ops.read_byte()?);
313 }
314 if rle_mode !=0 && rle_mode !=15 {
315 println!(" RLE len {} mode {}", rle_len, rle_mode);
316 }
317 copy_block(&mut self.frame, self.width, src_off, off, rle_mode);
318 }
319 }
320 off += 8 * self.width;
321 }
322 Ok(())
323 }
324 }
325
326 fn copy_block(frame: &mut [u8], stride: usize, mut src_off: usize, mut dst_off: usize, mode: u8) {
327 match mode {
328 0 => {
329 for _ in 0..8 {
330 for x in 0..8 {
331 frame[dst_off + x] = frame[src_off + x];
332 }
333 src_off += stride;
334 dst_off += stride;
335 }
336 },
337 // 1 -> copy 4x4 from src+4 to dst+1, copy 8x4 from src+1 to dst+1
338 // 2 -> copy 4x4 from src to dst, copy 8x4 from src+1 to dst+1
339 // 3 -> copy 8x4 from src+1 to dst+1
340 // 4 -> copy 8x4 from src to dst, copy 4x4 from src+1 to dst+1
341 // 5 -> copy 4x4 from src+4 to dst+1, copy 4x4 from src+1 to dst+1
342 // 6 -> ??? copy 8x4 from src to dst, copy 4x4 from src+1 to dst+1
343 // 7 -> copy 4x4 from src+1 to dst+1
344 // 8 -> copy 8x4 from src to dst, copy 4x4 from src+2 to dst+2
345 // 9 -> copy 4x4 from src+4 to dst+1, copy 4x4 from src+2 to dst+2
346 //10 -> copy 4x8 from src+2 to dst+2
347 //11 -> copy 4x4 from src+2 to dst+2
348 //12 -> copy 8x4 block
349 //13 -> copy 4x4 block
350 14 | 15 => {}, // skip
351 _ => unimplemented!(),
352 };
353 }
354
355 fn paint_8x8(dst: &mut [u8], stride: usize, pat: &[u8; 8], clrs: &[u8; 16]) {
356 for (line, &lpat) in dst.chunks_mut(stride).zip(pat.iter()) {
357 let mut mask = usize::from(lpat);
358 for dst in line[..8].iter_mut() {
359 *dst = clrs[mask & 1];
360 mask >>= 1;
361 }
362 }
363 }
364
365 fn paint_8x4_old(dst: &mut [u8], stride: usize, pat: &[u8; 8], clrs: &[u8; 16], mut mask: u32) {
366 for (y, line) in dst.chunks_mut(stride).take(4).enumerate() {
367 for (x, dst) in line[..8].iter_mut().enumerate() {
368 *dst = clrs[usize::from(pat[x / 2 + (y / 2) * 4] + ((mask & 1) as u8))];
369 mask >>= 1;
370 }
371 }
372 }
373
374 fn paint_8x4(dst: &mut [u8], stride: usize, pat: &[u8; 8], clrs: &[u8; 16], mut mask: u32) {
375 for (y, line) in dst.chunks_mut(stride).take(4).enumerate() {
376 for (x, dst) in line[..8].iter_mut().enumerate() {
377 *dst = clrs[usize::from(pat[x / 2 + (y / 2) * 4] - ((mask & 1) as u8))];
378 mask >>= 1;
379 }
380 }
381 }
382
383 fn paint_4x4_old(dst: &mut [u8], stride: usize, pat: &[u8; 8], clrs: &[u8; 16], mut mask: u16) {
384 for (line, pat) in dst.chunks_mut(stride).zip(pat.chunks_exact(2)) {
385 for (x, dst) in line[..4].iter_mut().enumerate() {
386 *dst = clrs[usize::from(pat[x / 2] + ((mask & 1) as u8))];
387 mask >>= 1;
388 }
389 }
390 }
391
392 fn paint_4x4(dst: &mut [u8], stride: usize, pat: &[u8; 8], clrs: &[u8; 16], mut mask: u16) {
393 for (line, pat) in dst.chunks_mut(stride).zip(pat.chunks_exact(2)) {
394 for (x, dst) in line[..4].iter_mut().enumerate() {
395 *dst = clrs[usize::from(pat[x / 2] - ((mask & 1) as u8))];
396 mask >>= 1;
397 }
398 }
399 }
400
401 impl NADecoder for DPVideoDecoder {
402 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
403 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
404 let width = vinfo.get_width();
405 let height = vinfo.get_height();
406 validate!((width & 7) == 0 && (height & 7) == 0);
407 if let Some(ref edata) = info.get_extradata() {
408 validate!(!edata.is_empty());
409 self.subtype = edata[0];
410 validate!(self.subtype >= 0x80);
411 if !matches!(self.subtype, 0x81 | 0x85 | 0x86 | 0x89 | 0x8A) {
412 return Err(DecoderError::NotImplemented);
413 }
414 match self.subtype {
415 0x81 | 0x8A => {
416 },
417 0x85 | 0x86 => {
418 validate!(edata.len() > 256 * 2);
419 for (dst, src) in self.pal.iter_mut().zip(edata[1..].chunks_exact(2)) {
420 *dst = read_u16be(src)?;
421 }
422 },
423 0x89 => {
424 },
425 _ => return Err(DecoderError::NotImplemented),
426 };
427 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(vinfo.get_width(), vinfo.get_height(), false, RGB555_FORMAT));
428 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
429 self.width = vinfo.get_width();
430 self.height = vinfo.get_height();
431 self.frame.resize(self.width * self.height, 0);
432
433 Ok(())
434 } else {
435 Err(DecoderError::InvalidData)
436 }
437 } else {
438 Err(DecoderError::InvalidData)
439 }
440 }
441 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
442 let src = pkt.get_buffer();
443
444 match self.subtype {
445 0x81 | 0x8A => {
446 validate!(src.len() > 12);
447 let mut mr = MemoryReader::new_read(&src);
448 let mut br = ByteReader::new(&mut mr);
449 let stype = br.read_byte()?;
450 validate!(stype == 0x81 || stype == 0x8A);
451 br.read_byte()?;
452 let size = usize::from(br.read_u16le()?);
453 if size + 4 < src.len() {
454 return Err(DecoderError::ShortData);
455 }
456 br.read_u32be()?; // timestamp
457 br.read_byte()?;
458 let pal_size = usize::from(br.read_byte()?);
459 let width = usize::from(br.read_byte()?) * 8;
460 let height = usize::from(br.read_byte()?) * 8;
461 validate!(width == self.width);
462 validate!(height == self.height);
463
464 for dst in self.pal.iter_mut().take(pal_size) {
465 *dst = br.read_u16le()?;
466 }
467
468 self.decode_81(&mut br)?;
469 },
470 0x85 | 0x86 | 0x89 => {
471 validate!(src.len() > 6);
472 let mut mr = MemoryReader::new_read(&src);
473 let mut br = ByteReader::new(&mut mr);
474
475 let pal_offset = usize::from(br.read_u16be()?);
476 let pal_size = usize::from(br.read_u16be()?);
477 let offset = usize::from(br.read_u16be()?);
478 validate!(offset <= src.len());
479 validate!(pal_offset + pal_size <= 256);
480 validate!(pal_size * 2 <= src.len());
481
482 for (dst, src) in self.pal[pal_offset..].iter_mut().zip(src[6..][..pal_size * 2].chunks_exact(2)) {
483 *dst = read_u16be(src)?;
484 }
485
486 self.decode_85(&src[6 + pal_size * 2..], &src[6 + offset..])?;
487 },
488 _ => unreachable!(),
489 };
490
491 let mut bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 0)?;
492 if let NABufferType::Video16(ref mut vbuf16) = bufinfo {
493 let stride = vbuf16.get_stride(0);
494 let dst = vbuf16.get_data_mut().unwrap();
495 for (dline, sline) in dst.chunks_exact_mut(stride).zip(self.frame.chunks_exact(self.width)) {
496 for (dst, &src) in dline.iter_mut().zip(sline.iter()) {
497 *dst = self.pal[usize::from(src)];
498 }
499 }
500 } else {
501 return Err(DecoderError::Bug);
502 }
503
504 let frm = NAFrame::new_from_pkt(pkt, self.info.clone(), bufinfo);
505 Ok(frm.into_ref())
506 }
507 fn flush(&mut self) {
508 }
509 }
510
511 impl NAOptionHandler for DPVideoDecoder {
512 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
513 fn set_options(&mut self, _options: &[NAOption]) { }
514 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
515 }
516
517 pub fn get_decoder() -> Box<dyn NADecoder + Send> {
518 Box::new(DPVideoDecoder::new())
519 }
520
521 #[cfg(test)]
522 mod test {
523 use nihav_core::codecs::RegisteredDecoders;
524 use nihav_core::demuxers::RegisteredDemuxers;
525 use nihav_codec_support::test::dec_video::*;
526 use crate::game_register_all_decoders;
527 use crate::game_register_all_demuxers;
528 #[test]
529 fn test_sga_dec_81() {
530 let mut dmx_reg = RegisteredDemuxers::new();
531 game_register_all_demuxers(&mut dmx_reg);
532 let mut dec_reg = RegisteredDecoders::new();
533 game_register_all_decoders(&mut dec_reg);
534
535 // sample from Double Switch
536 test_decoding("sga", "dp-sga", "assets/Game/sga/ALEXSTIL.AVC", None, &dmx_reg, &dec_reg,
537 ExpectedTestResult::MD5([0x8ae53caf, 0x9bd04a58, 0xf08f3ea9, 0x72b6fd05]));
538 }
539 #[test]
540 fn test_sga_dec_85() {
541 let mut dmx_reg = RegisteredDemuxers::new();
542 game_register_all_demuxers(&mut dmx_reg);
543 let mut dec_reg = RegisteredDecoders::new();
544 game_register_all_decoders(&mut dec_reg);
545
546 // sample from Night Trap
547 test_decoding("sga", "dp-sga", "assets/Game/sga/CRMOVIE", Some(32), &dmx_reg, &dec_reg,
548 ExpectedTestResult::MD5Frames(vec![
549 [0xa408375d, 0x3fc131f5, 0xd9ce5172, 0x30043774],
550 [0xa408375d, 0x3fc131f5, 0xd9ce5172, 0x30043774],
551 [0xa408375d, 0x3fc131f5, 0xd9ce5172, 0x30043774],
552 [0xa408375d, 0x3fc131f5, 0xd9ce5172, 0x30043774],
553 [0xa408375d, 0x3fc131f5, 0xd9ce5172, 0x30043774],
554 [0xa408375d, 0x3fc131f5, 0xd9ce5172, 0x30043774],
555 [0xa408375d, 0x3fc131f5, 0xd9ce5172, 0x30043774],
556 [0xa408375d, 0x3fc131f5, 0xd9ce5172, 0x30043774],
557 [0xa408375d, 0x3fc131f5, 0xd9ce5172, 0x30043774],
558 [0xa408375d, 0x3fc131f5, 0xd9ce5172, 0x30043774],
559 [0x2c18a4b2, 0x5771e98b, 0x90373b23, 0xc38b820d],
560 [0x2112a384, 0x8af91c70, 0xa8ba0a10, 0x166b754e],
561 [0x8824d580, 0xaba31634, 0x005f0c5e, 0xe45ac6c5],
562 [0x3f5551ba, 0xff75d014, 0xc7d22554, 0x2567f49f],
563 [0xf6257fd0, 0x457f6ff2, 0x0f5975bb, 0x85457c46],
564 [0xb7302db3, 0x5d384875, 0x8bce4edf, 0x9b25b176]]));
565 }
566 #[test]
567 fn test_sga_dec_86() {
568 let mut dmx_reg = RegisteredDemuxers::new();
569 game_register_all_demuxers(&mut dmx_reg);
570 let mut dec_reg = RegisteredDecoders::new();
571 game_register_all_decoders(&mut dec_reg);
572
573 //test_decode_images("sga", "assets/Game/sga/dplogo.dtv", "sga86", None, &dmx_reg, &dec_reg);
574 //panic!("end");
575
576 // sample from Corpse Killer
577 test_decoding("sga", "dp-sga", "assets/Game/sga/dplogo.dtv", Some(10), &dmx_reg, &dec_reg,
578 ExpectedTestResult::MD5Frames(vec![
579 [0x6dec0bbc, 0x9e81995b, 0x660a899b, 0xbc7954ca],
580 [0xce33d3e5, 0xcba3398d, 0x63a6ca73, 0xc3967861],
581 [0x55d3506a, 0x4b43c8e9, 0xac878ff2, 0xfd538d50],
582 [0x5c2abd0a, 0x0fc59df8, 0xfce6f84d, 0x577a6f0a],
583 [0x922e5500, 0xe16d523d, 0x44122da3, 0xf8d74675]]));
584 }
585 }
586
587 const OPCODE_TYPE: [u8; 128] = [
588 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04,
589 0x02, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04,
590 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02,
591 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02,
592 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
593 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
594 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
597 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
598 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
599 0x04, 0x04, 0x04, 0x04, 0x02, 0x00, 0x00, 0x00,
600 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
603 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
604 ];
605 const OPCODE_TO_PATTERN: [u8; 96] = [
606 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
607 0x00, 0x00, 0x01, 0x02, 0x06, 0x07, 0x08, 0x09,
608 0x01, 0x02, 0x03, 0x04, 0x05, 0x03, 0x06, 0x04,
609 0x07, 0x08, 0x05, 0x06, 0x09, 0x07, 0x08, 0x09,
610 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
611 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
612 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
613 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
614 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
615 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
616 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
617 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
618 ];
619 const PATTERN_COLOURS: [u8; 96] = [
620 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
621 0x02, 0x08, 0x08, 0x0a, 0x02, 0x02, 0x02, 0x02,
622 0x04, 0x06, 0x06, 0x08, 0x08, 0x0a, 0x0a, 0x08,
623 0x06, 0x04, 0x0a, 0x08, 0x02, 0x08, 0x08, 0x06,
624 0x10, 0x0e, 0x0e, 0x0c, 0x0e, 0x0c, 0x0c, 0x0a,
625 0x0e, 0x0c, 0x0c, 0x0a, 0x0c, 0x0a, 0x0a, 0x08,
626 0x10, 0x0e, 0x0e, 0x0c, 0x0e, 0x0c, 0x0c, 0x0a,
627 0x0e, 0x0c, 0x0c, 0x0a, 0x0c, 0x0a, 0x0a, 0x08,
628 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
629 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
630 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
631 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00
632 ];
633 const PATTERN_4X4: [[u8; 8]; 26] = [
634 [ 0x01, 0x03, 0x05, 0x03, 0x07, 0x07, 0x07, 0x07 ],
635 [ 0x01, 0x03, 0x01, 0x05, 0x07, 0x07, 0x07, 0x07 ],
636 [ 0x01, 0x03, 0x05, 0x07, 0x09, 0x09, 0x09, 0x09 ],
637 [ 0x01, 0x03, 0x01, 0x03, 0x05, 0x05, 0x05, 0x05 ],
638 [ 0x01, 0x01, 0x01, 0x01, 0x03, 0x05, 0x07, 0x05 ],
639 [ 0x01, 0x01, 0x01, 0x01, 0x03, 0x05, 0x03, 0x07 ],
640 [ 0x01, 0x01, 0x01, 0x01, 0x03, 0x05, 0x07, 0x09 ],
641 [ 0x01, 0x01, 0x01, 0x01, 0x03, 0x05, 0x03, 0x05 ],
642 [ 0x01, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03 ],
643 [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 ],
644 [ 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f ],
645 [ 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0b ],
646 [ 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x09, 0x0d ],
647 [ 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x09, 0x0b ],
648 [ 0x01, 0x03, 0x05, 0x03, 0x07, 0x09, 0x0b, 0x0d ],
649 [ 0x01, 0x03, 0x05, 0x03, 0x07, 0x09, 0x0b, 0x09 ],
650 [ 0x01, 0x03, 0x05, 0x03, 0x07, 0x09, 0x07, 0x0b ],
651 [ 0x01, 0x03, 0x05, 0x03, 0x07, 0x09, 0x07, 0x09 ],
652 [ 0x01, 0x03, 0x01, 0x05, 0x07, 0x09, 0x0b, 0x0d ],
653 [ 0x01, 0x03, 0x01, 0x05, 0x07, 0x09, 0x0b, 0x09 ],
654 [ 0x01, 0x03, 0x01, 0x05, 0x07, 0x09, 0x07, 0x0b ],
655 [ 0x01, 0x03, 0x01, 0x05, 0x07, 0x09, 0x07, 0x09 ],
656 [ 0x01, 0x03, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b ],
657 [ 0x01, 0x03, 0x01, 0x03, 0x05, 0x07, 0x09, 0x07 ],
658 [ 0x01, 0x03, 0x01, 0x03, 0x05, 0x07, 0x05, 0x09 ],
659 [ 0x01, 0x03, 0x01, 0x03, 0x05, 0x07, 0x05, 0x07 ]
660 ];
661 const PATTERN_8X4: [[u8; 8]; 26] = [
662 [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 ],
663 [ 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x03, 0x03 ],
664 [ 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x05, 0x05 ],
665 [ 0x01, 0x03, 0x05, 0x05, 0x07, 0x09, 0x05, 0x05 ],
666 [ 0x01, 0x03, 0x05, 0x05, 0x07, 0x07, 0x05, 0x05 ],
667 [ 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x07, 0x09 ],
668 [ 0x01, 0x01, 0x03, 0x05, 0x01, 0x01, 0x07, 0x07 ],
669 [ 0x01, 0x01, 0x03, 0x03, 0x05, 0x07, 0x03, 0x03 ],
670 [ 0x01, 0x01, 0x03, 0x03, 0x01, 0x01, 0x05, 0x07 ],
671 [ 0x01, 0x01, 0x03, 0x03, 0x05, 0x05, 0x03, 0x03 ],
672 [ 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0f ],
673 [ 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d, 0x0d ],
674 [ 0x01, 0x03, 0x05, 0x07, 0x09, 0x09, 0x0b, 0x0d ],
675 [ 0x01, 0x03, 0x05, 0x07, 0x09, 0x09, 0x0b, 0x0b ],
676 [ 0x01, 0x03, 0x05, 0x05, 0x07, 0x09, 0x0b, 0x0d ],
677 [ 0x01, 0x03, 0x05, 0x05, 0x07, 0x09, 0x0b, 0x0b ],
678 [ 0x01, 0x03, 0x05, 0x05, 0x07, 0x07, 0x09, 0x0b ],
679 [ 0x01, 0x03, 0x05, 0x05, 0x07, 0x07, 0x09, 0x09 ],
680 [ 0x01, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0d ],
681 [ 0x01, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0b, 0x0b ],
682 [ 0x01, 0x01, 0x03, 0x05, 0x07, 0x07, 0x09, 0x0b ],
683 [ 0x01, 0x01, 0x03, 0x05, 0x07, 0x07, 0x09, 0x09 ],
684 [ 0x01, 0x01, 0x03, 0x03, 0x05, 0x07, 0x09, 0x0b ],
685 [ 0x01, 0x01, 0x03, 0x03, 0x05, 0x07, 0x09, 0x09 ],
686 [ 0x01, 0x01, 0x03, 0x03, 0x05, 0x05, 0x07, 0x09 ],
687 [ 0x01, 0x01, 0x03, 0x03, 0x05, 0x05, 0x07, 0x07 ]
688 ];
689 const PATTERN_8X8: [[u8; 8]; 26] = [
690 [ 0; 8 ],
691 [ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa ],
692 [ 0xff, 0xff, 0x55, 0xaa, 0x55, 0xaa, 0x00, 0x00 ],
693 [ 0x5f, 0xaf, 0x57, 0xab, 0x15, 0x2a, 0x05, 0x0a ],
694 [ 0x17, 0x2b, 0x17, 0x2b, 0x17, 0x2b, 0x17, 0x2b ],
695 [ 0x05, 0x2a, 0x55, 0x2a, 0x55, 0xab, 0x57, 0xaf ],
696 [ 0x00, 0x00, 0x55, 0xaa, 0x55, 0xaa, 0xff, 0xff ],
697 [ 0x50, 0xa0, 0x54, 0xa8, 0xd5, 0xea, 0xf5, 0xfa ],
698 [ 0xd4, 0xe8, 0xd4, 0xe8, 0xd4, 0xe8, 0xd4, 0xe8 ],
699 [ 0xf5, 0xea, 0xd5, 0xaa, 0x54, 0xaa, 0x54, 0xa0 ],
700 [ 0x55, 0xaa, 0x55, 0xaa, 0x00, 0x00, 0x00, 0x00 ],
701 [ 0x55, 0x2a, 0x15, 0x0a, 0x05, 0x02, 0x01, 0x00 ],
702 [ 0x05, 0x0a, 0x05, 0x0a, 0x05, 0x0a, 0x05, 0x0a ],
703 [ 0x01, 0x00, 0x05, 0x02, 0x15, 0x0a, 0x55, 0x2a ],
704 [ 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x55, 0xaa ],
705 [ 0x00, 0x80, 0x40, 0xa0, 0x50, 0xa8, 0x54, 0xaa ],
706 [ 0x50, 0xa0, 0x50, 0xa0, 0x50, 0xa0, 0x50, 0xa0 ],
707 [ 0x54, 0xaa, 0x50, 0xa8, 0x40, 0xa0, 0x00, 0x80 ],
708 [ 0xff, 0xff, 0xff, 0xff, 0x55, 0xaa, 0x55, 0xaa ],
709 [ 0x7f, 0xff, 0x5f, 0xbf, 0x57, 0xaf, 0x55, 0xab ],
710 [ 0x5f, 0xaf, 0x5f, 0xaf, 0x5f, 0xaf, 0x5f, 0xaf ],
711 [ 0x55, 0xab, 0x57, 0xaf, 0x5f, 0xbf, 0x7f, 0xff ],
712 [ 0x55, 0xaa, 0x55, 0xaa, 0xff, 0xff, 0xff, 0xff ],
713 [ 0xd5, 0xaa, 0xf5, 0xea, 0xfd, 0xfa, 0xff, 0xfe ],
714 [ 0xf5, 0xfa, 0xf5, 0xfa, 0xf5, 0xfa, 0xf5, 0xfa ],
715 [ 0xff, 0xfe, 0xfd, 0xfa, 0xf5, 0xea, 0xd5, 0xaa ]
716 ];
717
718 const PATTERN_4X4_OLD: [[u8; 8]; 26] = [
719 [ 0x00, 0x02, 0x04, 0x02, 0x06, 0x06, 0x06, 0x06 ],
720 [ 0x00, 0x02, 0x00, 0x04, 0x06, 0x06, 0x06, 0x06 ],
721 [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x08, 0x08, 0x08 ],
722 [ 0x00, 0x02, 0x00, 0x02, 0x04, 0x04, 0x04, 0x04 ],
723 [ 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x04 ],
724 [ 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x02, 0x06 ],
725 [ 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x08 ],
726 [ 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x02, 0x04 ],
727 [ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02 ],
728 [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
729 [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e ],
730 [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0a ],
731 [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x08, 0x0c ],
732 [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x08, 0x0a ],
733 [ 0x00, 0x02, 0x04, 0x02, 0x06, 0x08, 0x0a, 0x0c ],
734 [ 0x00, 0x02, 0x04, 0x02, 0x06, 0x08, 0x0a, 0x08 ],
735 [ 0x00, 0x02, 0x04, 0x02, 0x06, 0x08, 0x06, 0x0a ],
736 [ 0x00, 0x02, 0x04, 0x02, 0x06, 0x08, 0x06, 0x08 ],
737 [ 0x00, 0x02, 0x00, 0x04, 0x06, 0x08, 0x0a, 0x0c ],
738 [ 0x00, 0x02, 0x00, 0x04, 0x06, 0x08, 0x0a, 0x08 ],
739 [ 0x00, 0x02, 0x00, 0x04, 0x06, 0x08, 0x06, 0x0a ],
740 [ 0x00, 0x02, 0x00, 0x04, 0x06, 0x08, 0x06, 0x08 ],
741 [ 0x00, 0x02, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a ],
742 [ 0x00, 0x02, 0x00, 0x02, 0x04, 0x06, 0x08, 0x06 ],
743 [ 0x00, 0x02, 0x00, 0x02, 0x04, 0x06, 0x04, 0x08 ],
744 [ 0x00, 0x02, 0x00, 0x02, 0x04, 0x06, 0x04, 0x06 ]
745 ];
746 const PATTERN_8X4_OLD: [[u8; 8]; 26] = [
747 [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ],
748 [ 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02 ],
749 [ 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04 ],
750 [ 0x00, 0x02, 0x04, 0x04, 0x06, 0x08, 0x04, 0x04 ],
751 [ 0x00, 0x02, 0x04, 0x04, 0x06, 0x06, 0x04, 0x04 ],
752 [ 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x06, 0x08 ],
753 [ 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x06, 0x06 ],
754 [ 0x00, 0x00, 0x02, 0x02, 0x04, 0x06, 0x02, 0x02 ],
755 [ 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x06 ],
756 [ 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x02, 0x02 ],
757 [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e ],
758 [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0c ],
759 [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x08, 0x0a, 0x0c ],
760 [ 0x00, 0x02, 0x04, 0x06, 0x08, 0x08, 0x0a, 0x0a ],
761 [ 0x00, 0x02, 0x04, 0x04, 0x06, 0x08, 0x0a, 0x0c ],
762 [ 0x00, 0x02, 0x04, 0x04, 0x06, 0x08, 0x0a, 0x0a ],
763 [ 0x00, 0x02, 0x04, 0x04, 0x06, 0x06, 0x08, 0x0a ],
764 [ 0x00, 0x02, 0x04, 0x04, 0x06, 0x06, 0x08, 0x08 ],
765 [ 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c ],
766 [ 0x00, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0a ],
767 [ 0x00, 0x00, 0x02, 0x04, 0x06, 0x06, 0x08, 0x0a ],
768 [ 0x00, 0x00, 0x02, 0x04, 0x06, 0x06, 0x08, 0x08 ],
769 [ 0x00, 0x00, 0x02, 0x02, 0x04, 0x06, 0x08, 0x0a ],
770 [ 0x00, 0x00, 0x02, 0x02, 0x04, 0x06, 0x08, 0x08 ],
771 [ 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x06, 0x08 ],
772 [ 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x06, 0x06 ]
773 ];