vmd: raise unpacked buffer size to a factor four
[nihav.git] / nihav-game / src / codecs / vmd.rs
1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 use nihav_codec_support::codecs::HAMShuffler;
4 use std::str::FromStr;
5 use std::sync::Arc;
6
7 macro_rules! lz_op {
8 (read; $dst:ident, $dpos:expr, $window:ident, $wpos:expr, $br:expr, $dst_size:expr) => {
9 validate!($dpos < $dst_size);
10 let b = $br.read_byte()?;
11 $dst[$dpos] = b;
12 $dpos += 1;
13 $window[$wpos] = b;
14 $wpos = ($wpos + 1) & 0xFFF;
15 };
16 (copy; $dst:ident, $dpos:expr, $window:ident, $wpos:expr, $off:expr, $dst_size:expr) => {
17 let b = $window[$off];
18 validate!($dpos < $dst_size);
19 $dst[$dpos] = b;
20 $dpos += 1;
21 $window[$wpos] = b;
22 $wpos = ($wpos + 1) & 0xFFF;
23 $off = ($off + 1) & 0xFFF;
24 };
25 }
26 fn lz_unpack(br: &mut ByteReader, dst: &mut [u8]) -> DecoderResult<()> {
27 let mut window: [u8; 0x1000] = [0x20; 0x1000];
28
29 let dst_size = br.read_u32le()? as usize;
30 validate!(dst_size <= dst.len());
31 let mut pos;
32 let esc_len;
33 if br.peek_u32le()? == 0x56781234 {
34 br.read_skip(4)?;
35 pos = 0x111;
36 esc_len = 15;
37 } else {
38 pos = 0xFEE;
39 esc_len = 255;
40 }
41
42 let mut opos = 0;
43 while br.left() > 0 && opos < dst_size {
44 let op = br.read_byte()?;
45 if (op == 0xFF) && (br.left() > 8) {
46 for _ in 0..8 {
47 lz_op!(read; dst, opos, window, pos, br, dst_size);
48 }
49 } else {
50 for i in 0..8 {
51 if opos == dst_size { break; }
52 let is_literal = ((op >> i) & 1) != 0;
53 if is_literal {
54 lz_op!(read; dst, opos, window, pos, br, dst_size);
55 } else {
56 let b0 = br.read_byte()? as usize;
57 let b1 = br.read_byte()? as usize;
58 let mut off = b0 | ((b1 & 0xF0) << 4);
59 let mut len = b1 & 0xF;
60 if len == esc_len {
61 len = (br.read_byte()? as usize) + esc_len;
62 }
63 for _ in 0..len+3 {
64 lz_op!(copy; dst, opos, window, pos, off, dst_size);
65 }
66 }
67 }
68 }
69 }
70 Ok(())
71 }
72
73 fn rle_unpack(br: &mut ByteReader, len: usize, dst: &mut [u8]) -> DecoderResult<()> {
74 let end = br.tell() + (len as u64);
75 let mut dpos = 0;
76 if (len & 1) != 0 {
77 dst[dpos] = br.read_byte()?;
78 dpos += 1;
79 }
80 while dpos < dst.len() && br.tell() < end {
81 let val = br.read_byte()?;
82 let len = ((val & 0x7F) as usize) * 2;
83 validate!(dpos + len <= dst.len());
84 if (val & 0x80) != 0 {
85 let dst = &mut dst[dpos..][..len];
86 br.read_buf(dst)?;
87 } else {
88 let val = br.read_byte()?;
89 for i in 0..len {
90 dst[dpos + i] = val;
91 }
92 }
93 dpos += len;
94 }
95 Ok(())
96 }
97
98 fn decode_frame_data(br: &mut ByteReader, dst: &mut [u8], mut dpos: usize, stride: usize, w: usize, h: usize, method: u8) -> DecoderResult<bool> {
99 match method {
100 1 => {
101 for _ in 0..h {
102 let mut x = 0;
103 while x < w {
104 let val = br.read_byte()?;
105 let len = ((val & 0x7F) as usize) + 1;
106 validate!(x + len <= w);
107 if (val & 0x80) != 0 {
108 let pix = &mut dst[dpos + x..][..len];
109 br.read_buf(pix)?;
110 } // otherwise skip already existing data
111 x += len;
112 }
113 dpos += stride;
114 }
115 Ok(false)
116 },
117 2 => {
118 for _ in 0..h {
119 let pix = &mut dst[dpos..][..w];
120 br.read_buf(pix)?;
121 dpos += stride;
122 }
123 Ok(true)
124 },
125 3 => {
126 for _ in 0..h {
127 let mut x = 0;
128 while x < w {
129 let val = br.read_byte()?;
130 let len = ((val & 0x7F) as usize) + 1;
131 validate!(x + len <= w);
132 if (val & 0x80) != 0 {
133 let pix = &mut dst[dpos + x..][..len];
134 if br.peek_byte()? == 0xFF {
135 br.read_skip(1)?;
136 rle_unpack(br, len, pix)?;
137 } else {
138 br.read_buf(pix)?;
139 }
140 } // otherwise data is already there
141 x += len;
142 }
143 dpos += stride;
144 }
145 Ok(false)
146 },
147 _ => Err(DecoderError::InvalidData),
148 }
149 }
150
151 struct VMDVideoDecoder {
152 info: NACodecInfoRef,
153 pal: [u8; 768],
154 buf: Vec<u8>,
155 width: usize,
156 height: usize,
157 xoff: usize,
158 yoff: usize,
159 hams: HAMShuffler,
160 }
161
162 impl VMDVideoDecoder {
163 fn new() -> Self {
164 Self {
165 info: NACodecInfoRef::default(),
166 pal: [0; 768],
167 buf: Vec::new(),
168 width: 0,
169 height: 0,
170 xoff: 0,
171 yoff: 0,
172 hams: HAMShuffler::default(),
173 }
174 }
175 fn decode_frame(&mut self, br: &mut ByteReader, buf: &mut NAVideoBuffer<u8>) -> DecoderResult<bool> {
176 let paloff = buf.get_offset(1);
177 let stride = buf.get_stride(0);
178 let data = buf.get_data_mut().unwrap();
179 let dst = data.as_mut_slice();
180
181 let frame_x = br.read_u16le()? as usize;
182 let frame_y = br.read_u16le()? as usize;
183 let frame_l = br.read_u16le()? as usize;
184 let frame_d = br.read_u16le()? as usize;
185 br.read_skip(1)?;
186 let flags = br.read_byte()?;
187 let has_pal = (flags & 0x02) != 0;
188 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
189 return Ok(false);
190 }
191 validate!(frame_x >= self.xoff && frame_y >= self.yoff);
192 validate!(frame_l >= frame_x && frame_d >= frame_y);
193 validate!(frame_l - self.xoff < self.width && frame_d - self.yoff < self.height);
194
195 if has_pal {
196 br.read_skip(2)?;
197 for e in self.pal.iter_mut() {
198 let val = br.read_byte()?;
199 *e = (val << 2) | (val >> 4);
200 }
201 }
202
203 let dpal = &mut dst[paloff..][..768];
204 dpal.copy_from_slice(&self.pal[0..]);
205
206 if br.left() == 0 { return Ok(false); }
207
208 let w = frame_l + 1 - frame_x;
209 let h = frame_d + 1 - frame_y;
210 let dpos = frame_x - self.xoff + (frame_y - self.yoff) * stride;
211
212 let method = br.read_byte()?;
213 let is_intra;
214 if (method & 0x80) != 0 {
215 validate!(!self.buf.is_empty());
216 lz_unpack(br, &mut self.buf)?;
217 let mut mr = MemoryReader::new_read(&self.buf);
218 let mut buf_br = ByteReader::new(&mut mr);
219 is_intra = decode_frame_data(&mut buf_br, dst, dpos, stride, w, h, method & 0x7F)?;
220 } else {
221 is_intra = decode_frame_data(br, dst, dpos, stride, w, h, method & 0x7F)?;
222 }
223 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
224 }
225 }
226
227 impl NADecoder for VMDVideoDecoder {
228 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
229 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
230 self.width = vinfo.get_width();
231 self.height = vinfo.get_height();
232 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(self.width, self.height, false, PAL8_FORMAT));
233 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
234 validate!(info.get_extradata().is_some());
235
236 if let Some(ref edata) = info.get_extradata() {
237 validate!(edata.len() == 0x330);
238 let unp_size = read_u32le(&edata[800..])? as usize;
239 validate!(unp_size < self.width * self.height * 4 + 64); // just for sanity
240 self.buf.resize(unp_size, 0);
241 for i in 0..768 {
242 let el = edata[28 + i];
243 self.pal[i] = (el << 2) | (el >> 4);
244 }
245 self.xoff = read_u16le(&edata[8..])? as usize;
246 self.yoff = read_u16le(&edata[10..])? as usize;
247 }
248
249 Ok(())
250 } else {
251 Err(DecoderError::InvalidData)
252 }
253 }
254 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
255 let src = pkt.get_buffer();
256 validate!(src.len() >= 10);
257
258 let mut mr = MemoryReader::new_read(&src);
259 let mut br = ByteReader::new(&mut mr);
260
261 let mut buf;
262 let bufret = self.hams.clone_ref();
263 if let Some(bbuf) = bufret {
264 buf = bbuf;
265 } else {
266 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
267 buf = bufinfo.get_vbuf().unwrap();
268 self.hams.add_frame(buf);
269 buf = self.hams.get_output_frame().unwrap();
270 }
271
272 let is_intra = self.decode_frame(&mut br, &mut buf)?;
273
274 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), NABufferType::Video(buf));
275 frm.set_keyframe(is_intra);
276 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
277 Ok(frm.into_ref())
278 }
279 fn flush(&mut self) {
280 self.hams.clear();
281 }
282 }
283
284
285 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
286 Box::new(VMDVideoDecoder::new())
287 }
288
289 #[derive(Clone,Copy,PartialEq)]
290 enum VMDAudioMode {
291 U8,
292 DPCM,
293 StereoDPCM,
294 }
295
296 struct VMDAudioDecoder {
297 ainfo: NAAudioInfo,
298 info: Arc<NACodecInfo>,
299 chmap: NAChannelMap,
300 blk_align: usize,
301 blk_size: usize,
302 mode: VMDAudioMode,
303 pred: [i32; 2],
304 last_byte: Option<u8>,
305 is_odd: bool,
306 ch: usize,
307 }
308
309 const SOL_AUD_STEPS16: [i16; 128] = [
310 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
311 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
312 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
313 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
314 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
315 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
316 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
317 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
318 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
319 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
320 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
321 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
322 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
323 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
324 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
325 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
326 ];
327
328 impl VMDAudioDecoder {
329 fn new() -> Self {
330 Self {
331 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
332 info: NACodecInfo::new_dummy(),
333 chmap: NAChannelMap::new(),
334 blk_align: 0,
335 blk_size: 0,
336 mode: VMDAudioMode::U8,
337 pred: [0; 2],
338 last_byte: None,
339 is_odd: false,
340 ch: 0,
341 }
342 }
343 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
344 let channels = self.chmap.num_channels();
345 let mut off = [0, off1];
346 for _ in 0..nblocks {
347 if (mask & 1) != 0 {
348 for ch in 0..channels {
349 for i in 0..self.blk_align {
350 dst[off[ch] + i] = 0;
351 }
352 off[ch] += self.blk_align;
353 }
354 } else {
355 let mut pred: [i32; 2] = [0; 2];
356 for ch in 0..channels {
357 pred[ch] = i32::from(br.read_u16le()?);
358 dst[off[ch]] = pred[ch] as i16;
359 off[ch] += 1;
360 }
361 let mut ch = 0;
362 let flip_ch = if channels == 2 { 1 } else { 0 };
363 for _ in channels..self.blk_align*channels {
364 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
365 //pred[ch] = pred[ch].max(-32768).min(32767);
366 dst[off[ch]] = pred[ch] as i16;
367 off[ch] += 1;
368 ch ^= flip_ch;
369 }
370 }
371 mask >>= 1;
372 }
373 validate!(br.left() == 0);
374 Ok(())
375 }
376 fn pred16(pred: i32, val: u8) -> i32 {
377 if (val & 0x80) != 0 {
378 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
379 } else {
380 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
381 }
382 }
383 fn cvt_u8(val: u8) -> u8 {
384 val ^ 0x80
385 }
386 }
387
388 impl NADecoder for VMDAudioDecoder {
389 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
390 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
391 let fmt;
392 let channels = ainfo.get_channels() as usize;
393 let edata = info.get_extradata();
394 let flags = if let Some(ref buf) = edata {
395 validate!(buf.len() >= 2);
396 (buf[0] as u16) | ((buf[1] as u16) << 8)
397 } else {
398 0
399 };
400 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
401 if ainfo.get_format().get_bits() == 8 {
402 self.blk_size = ainfo.get_block_len();
403 self.blk_align = ainfo.get_block_len() / channels;
404 if (flags & 0x8000) == 0 {
405 fmt = SND_U8_FORMAT;
406 self.mode = VMDAudioMode::U8;
407 } else {
408 fmt = SND_S16_FORMAT;
409 self.mode = VMDAudioMode::StereoDPCM;
410 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
411 }
412 } else {
413 fmt = SND_S16P_FORMAT;
414 self.blk_size = (ainfo.get_block_len() + 1) * channels;
415 self.blk_align = ainfo.get_block_len();
416 self.mode = VMDAudioMode::DPCM;
417 };
418 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
419 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone()));
420 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
421 Ok(())
422 } else {
423 Err(DecoderError::InvalidData)
424 }
425 }
426 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
427 let info = pkt.get_stream().get_info();
428 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
429 let pktbuf = pkt.get_buffer();
430 validate!(pktbuf.len() >= 6);
431 let mut mr = MemoryReader::new_read(&pktbuf);
432 let mut br = ByteReader::new(&mut mr);
433 let blk_type = br.read_byte()?;
434 br.read_skip(9)?;
435 let mask;
436 let nblocks;
437 if blk_type == 2 { // initial
438 mask = br.read_u32le()?;
439 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
440 } else if blk_type == 3 { // silence
441 mask = 1;
442 nblocks = 1;
443 } else {
444 mask = 0;
445 nblocks = 1;
446 }
447 let mut samples = nblocks * self.blk_align;
448 if self.mode == VMDAudioMode::StereoDPCM && self.is_odd {
449 samples += (nblocks + if self.last_byte.is_some() { 1 } else { 0 }) / 2;
450 }
451 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
452 match self.mode {
453 VMDAudioMode::DPCM => {
454 let mut adata = abuf.get_abuf_i16().unwrap();
455 let off1 = adata.get_offset(1);
456 let mut dst = adata.get_data_mut().unwrap();
457 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
458 },
459 VMDAudioMode::U8 => {
460 let mut adata = abuf.get_abuf_u8().unwrap();
461 let dst = adata.get_data_mut().unwrap();
462 let mut doff = 0;
463 let mut mask = mask;
464 let channels = self.chmap.num_channels();
465 for _ in 0..nblocks {
466 if (mask & 1) != 0 {
467 for i in 0..self.blk_align * channels {
468 dst[doff + i] = 128;
469 }
470 } else if channels == 1 {
471 for i in 0..self.blk_size {
472 dst[doff + i] = br.read_byte()?;
473 }
474 } else {
475 for i in 0..self.blk_size {
476 let val = Self::cvt_u8(br.read_byte()?);
477 dst[doff + i] = val;
478 }
479 }
480 doff += self.blk_align * channels;
481 mask >>= 1;
482 }
483 },
484 VMDAudioMode::StereoDPCM => {
485 let mut adata = abuf.get_abuf_i16().unwrap();
486 let dst = adata.get_data_mut().unwrap();
487 let mut doff = 0;
488 let mut mask = mask;
489 let mut ch = self.ch;
490 for _ in 0..nblocks {
491 let put_sample = self.last_byte.is_some();
492 if let (true, Some(val)) = (self.is_odd, self.last_byte) {
493 self.pred[ch] = Self::pred16(self.pred[ch], val);
494 dst[doff] = self.pred[ch] as i16;
495 doff += 1;
496 ch ^= 1;
497 self.last_byte = None;
498 }
499 if (mask & 1) != 0 {
500 for i in 0..self.blk_align {
501 dst[doff + i * 2 + 0] = self.pred[ch] as i16;
502 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
503 }
504 if self.is_odd {
505 if put_sample {
506 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
507 doff += 1;
508 ch ^= 1;
509 } else {
510 self.last_byte = Some(0);
511 }
512 }
513 } else {
514 for i in 0..self.blk_align {
515 self.pred[ch] = Self::pred16(self.pred[ch], br.read_byte()?);
516 dst[doff + i * 2] = self.pred[ch] as i16;
517 self.pred[ch ^ 1] = Self::pred16(self.pred[ch ^ 1], br.read_byte()?);
518 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
519 }
520 if self.is_odd {
521 let val = br.read_byte()?;
522 if put_sample {
523 self.pred[ch] = Self::pred16(self.pred[ch], val);
524 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
525 doff += 1;
526 ch ^= 1;
527 } else {
528 self.last_byte = Some(val);
529 }
530 }
531 }
532 doff += self.blk_align * 2;
533 mask >>= 1;
534 }
535 self.ch = ch;
536 },
537 };
538
539 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
540 frm.set_duration(Some(samples as u64));
541 frm.set_keyframe(true);
542 Ok(frm.into_ref())
543 } else {
544 Err(DecoderError::InvalidData)
545 }
546 }
547 fn flush(&mut self) {
548 }
549 }
550
551 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
552 Box::new(VMDAudioDecoder::new())
553 }
554
555 #[cfg(test)]
556 mod test {
557 use nihav_core::codecs::RegisteredDecoders;
558 use nihav_core::demuxers::RegisteredDemuxers;
559 use nihav_codec_support::test::dec_video::*;
560 use crate::game_register_all_codecs;
561 use crate::game_register_all_demuxers;
562 #[test]
563 fn test_vmd_video() {
564 let mut dmx_reg = RegisteredDemuxers::new();
565 game_register_all_demuxers(&mut dmx_reg);
566 let mut dec_reg = RegisteredDecoders::new();
567 game_register_all_codecs(&mut dec_reg);
568
569 test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
570 ExpectedTestResult::MD5Frames(vec![
571 [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
572 [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
573 [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
574 [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
575 [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
576 [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
577 [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
578 [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
579 [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
580 [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
581 [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
582 }
583 #[test]
584 fn test_vmd_audio_u8() {
585 let mut dmx_reg = RegisteredDemuxers::new();
586 game_register_all_demuxers(&mut dmx_reg);
587 let mut dec_reg = RegisteredDecoders::new();
588 game_register_all_codecs(&mut dec_reg);
589
590 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
591 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
592 }
593 #[test]
594 fn test_vmd_audio_s16_old() {
595 let mut dmx_reg = RegisteredDemuxers::new();
596 game_register_all_demuxers(&mut dmx_reg);
597 let mut dec_reg = RegisteredDecoders::new();
598 game_register_all_codecs(&mut dec_reg);
599
600 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
601 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
602 }
603 #[test]
604 fn test_vmd_audio_s16_new() {
605 let mut dmx_reg = RegisteredDemuxers::new();
606 game_register_all_demuxers(&mut dmx_reg);
607 let mut dec_reg = RegisteredDecoders::new();
608 game_register_all_codecs(&mut dec_reg);
609
610 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
611 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));
612 }
613 }