1 use nihav_core::codecs::*;
2 use nihav_core::io::byteio::*;
3 use nihav_codec_support::codecs::imaadpcm::*;
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()?;
14 $wpos = ($wpos + 1) & 0xFFF;
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);
22 $wpos = ($wpos + 1) & 0xFFF;
23 $off = ($off + 1) & 0xFFF;
26 fn lz_unpack(br: &mut ByteReader, dst: &mut [u8]) -> DecoderResult<()> {
27 let mut window: [u8; 0x1000] = [0x20; 0x1000];
29 let dst_size = br.read_u32le()? as usize;
30 validate!(dst_size <= dst.len());
33 if br.peek_u32le()? == 0x56781234 {
43 while br.left() > 0 && opos < dst_size {
44 let op = br.read_byte()?;
45 if (op == 0xFF) && (br.left() > 8) {
47 lz_op!(read; dst, opos, window, pos, br, dst_size);
51 if opos == dst_size { break; }
52 let is_literal = ((op >> i) & 1) != 0;
54 lz_op!(read; dst, opos, window, pos, br, dst_size);
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;
61 len = (br.read_byte()? as usize) + esc_len;
64 lz_op!(copy; dst, opos, window, pos, off, dst_size);
73 fn rle_unpack(br: &mut ByteReader, len: usize, dst: &mut [u8]) -> DecoderResult<()> {
74 let end = br.tell() + (len as u64);
77 dst[dpos] = br.read_byte()?;
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];
88 let val1 = br.read_byte()?;
89 let val2 = br.read_byte()?;
90 for i in (0..len).step_by(2) {
92 dst[dpos + i + 1] = val2;
100 fn decode_frame_data(br: &mut ByteReader, dst: &mut [u8], mut dpos: usize, stride: usize, w: usize, h: usize, method: u8) -> DecoderResult<bool> {
106 let val = br.read_byte()?;
107 let len = ((val & 0x7F) as usize) + 1;
108 validate!(x + len <= w);
109 if (val & 0x80) != 0 {
110 let pix = &mut dst[dpos + x..][..len];
112 } // otherwise skip already existing data
121 let pix = &mut dst[dpos..][..w];
131 let val = br.read_byte()?;
132 let len = ((val & 0x7F) as usize) + 1;
133 validate!(x + len <= w);
134 if (val & 0x80) != 0 {
135 let pix = &mut dst[dpos + x..][..len];
136 if br.peek_byte()? == 0xFF {
138 rle_unpack(br, len, pix)?;
142 } // otherwise data is already there
149 _ => Err(DecoderError::InvalidData),
153 struct VMDVideoDecoder {
154 info: NACodecInfoRef,
168 impl VMDVideoDecoder {
171 info: NACodecInfoRef::default(),
174 framebuf: Vec::new(),
185 fn decode_frame(&mut self, br: &mut ByteReader) -> DecoderResult<bool> {
186 let frame_x = br.read_u16le()? as usize;
187 let frame_y = br.read_u16le()? as usize;
188 let frame_r = br.read_u16le()? as usize;
189 let frame_d = br.read_u16le()? as usize;
191 let flags = br.read_byte()?;
192 let has_pal = (flags & 0x02) != 0 && !self.is_16bit && !self.is_24bit;
193 if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_r == 0xFFFF) && (frame_d == 0xFFFF) {
196 validate!(frame_x >= self.xoff && frame_y >= self.yoff);
197 validate!(frame_r >= frame_x && frame_d >= frame_y);
198 validate!(frame_r - self.xoff < self.width && frame_d - self.yoff < self.height);
202 for e in self.pal.iter_mut() {
203 let val = br.read_byte()?;
204 *e = (val << 2) | (val >> 4);
208 if br.left() == 0 { return Ok(false); }
210 let bpp = if (!self.is_16bit && !self.is_24bit) || self.ver1 < 2 {
212 } else if self.is_16bit {
217 let w = (frame_r + 1 - frame_x) * bpp;
218 let h = frame_d + 1 - frame_y;
219 let stride = self.width;
220 let dpos = (frame_x - self.xoff) * bpp + (frame_y - self.yoff) * stride;
222 let method = br.read_byte()?;
224 if (method & 0x80) != 0 {
225 validate!(!self.buf.is_empty());
226 lz_unpack(br, &mut self.buf)?;
227 let mut mr = MemoryReader::new_read(&self.buf);
228 let mut buf_br = ByteReader::new(&mut mr);
229 is_intra = decode_frame_data(&mut buf_br, &mut self.framebuf, dpos, stride, w, h, method & 0x7F)?;
231 is_intra = decode_frame_data(br, &mut self.framebuf, dpos, stride, w, h, method & 0x7F)?;
233 Ok(is_intra && frame_x == 0 && frame_y == 0 && w == self.width && h == self.height)
237 const RGB555_FORMAT: NAPixelFormaton = NAPixelFormaton { model: ColorModel::RGB(RGBSubmodel::RGB), components: 3,
239 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 10, comp_offs: 0, next_elem: 2 }),
240 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 5, comp_offs: 1, next_elem: 2 }),
241 Some(NAPixelChromaton{ h_ss: 0, v_ss: 0, packed: true, depth: 5, shift: 0, comp_offs: 2, next_elem: 2 }),
243 elem_size: 2, be: false, alpha: false, palette: false };
245 impl NADecoder for VMDVideoDecoder {
246 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
247 if let NACodecTypeInfo::Video(vinfo) = info.get_properties() {
248 self.width = vinfo.get_width();
249 self.height = vinfo.get_height();
250 validate!(info.get_extradata().is_some());
252 if let Some(ref edata) = info.get_extradata() {
253 validate!(edata.len() == 0x330);
254 let unp_size = read_u32le(&edata[800..])? as usize;
255 validate!(unp_size < self.width * self.height * 4 + 64); // just for sanity
256 self.buf.resize(unp_size, 0);
258 let el = edata[28 + i];
259 self.pal[i] = (el << 2) | (el >> 4);
261 self.xoff = read_u16le(&edata[8..])? as usize;
262 self.yoff = read_u16le(&edata[10..])? as usize;
263 self.ver1 = edata[2];
264 self.ver2 = edata[4];
268 let (disp_width, fmt) = if self.ver2 < 5 {
269 (self.width, PAL8_FORMAT)
270 } else if self.ver2 < 13 {
271 self.is_24bit = true;
275 validate!(self.width % 3 == 0);
276 (self.width / 3, RGB24_FORMAT)
278 self.is_16bit = true;
282 (self.width / 2, RGB555_FORMAT)
284 self.framebuf = vec!(0; self.width * self.height);
286 let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(disp_width, self.height, false, fmt));
287 self.info = NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()).into_ref();
291 Err(DecoderError::InvalidData)
294 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
295 let src = pkt.get_buffer();
296 validate!(src.len() >= 10);
298 let mut mr = MemoryReader::new_read(&src);
299 let mut br = ByteReader::new(&mut mr);
301 let is_intra = self.decode_frame(&mut br)?;
303 let bufinfo = alloc_video_buffer(self.info.get_properties().get_video_info().unwrap(), 4)?;
306 let mut buf = bufinfo.get_vbuf().unwrap();
307 let stride = buf.get_stride(0);
308 let paloff = buf.get_offset(1);
309 let data = buf.get_data_mut().unwrap();
310 for (inrow, outrow) in self.framebuf.chunks(self.width).zip(data.chunks_mut(stride)) {
311 (&mut outrow[..self.width]).copy_from_slice(inrow);
314 (&mut data[paloff..][..768]).copy_from_slice(&self.pal);
316 videobuf = if !self.is_24bit { NABufferType::Video(buf) } else { NABufferType::VideoPacked(buf) };
318 let mut buf = bufinfo.get_vbuf16().unwrap();
319 let stride = buf.get_stride(0);
320 let data = buf.get_data_mut().unwrap();
321 for (inrow, outrow) in self.framebuf.chunks(self.width).zip(data.chunks_mut(stride)) {
322 for i in (0..self.width).step_by(2) {
323 outrow[i >> 1] = read_u16le(&inrow[i..])?;
326 videobuf = NABufferType::Video16(buf);
329 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), videobuf);
330 frm.set_keyframe(is_intra);
331 frm.set_frame_type(if is_intra { FrameType::I } else { FrameType::P });
334 fn flush(&mut self) {
339 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
340 Box::new(VMDVideoDecoder::new())
343 #[derive(Clone,Copy,PartialEq)]
351 struct VMDAudioDecoder {
353 info: Arc<NACodecInfo>,
359 last_byte: Option<u8>,
364 const SOL_AUD_STEPS16: [i16; 128] = [
365 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
366 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
367 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
368 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
369 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
370 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
371 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
372 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
373 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
374 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
375 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
376 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
377 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
378 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
379 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
380 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
383 impl VMDAudioDecoder {
386 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
387 info: NACodecInfo::new_dummy(),
388 chmap: NAChannelMap::new(),
391 mode: VMDAudioMode::U8,
398 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
399 let channels = self.chmap.num_channels();
400 let mut off = [0, off1];
401 for _ in 0..nblocks {
403 for ch in 0..channels {
404 for i in 0..self.blk_align {
405 dst[off[ch] + i] = 0;
407 off[ch] += self.blk_align;
410 let mut pred: [i32; 2] = [0; 2];
411 for ch in 0..channels {
412 pred[ch] = i32::from(br.read_u16le()?);
413 dst[off[ch]] = pred[ch] as i16;
417 let flip_ch = if channels == 2 { 1 } else { 0 };
418 for _ in channels..self.blk_align*channels {
419 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
420 //pred[ch] = pred[ch].max(-32768).min(32767);
421 dst[off[ch]] = pred[ch] as i16;
428 validate!(br.left() == 0);
431 fn pred16(pred: i32, val: u8) -> i32 {
432 if (val & 0x80) != 0 {
433 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
435 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
438 fn cvt_u8(val: u8) -> u8 {
443 impl NADecoder for VMDAudioDecoder {
444 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
445 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
447 let channels = ainfo.get_channels() as usize;
448 let edata = info.get_extradata();
449 let flags = if let Some(ref buf) = edata {
450 validate!(buf.len() >= 2);
451 (buf[0] as u16) | ((buf[1] as u16) << 8)
455 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
456 if ainfo.get_format().get_bits() == 8 {
457 self.blk_size = ainfo.get_block_len();
458 self.blk_align = ainfo.get_block_len() / channels;
459 if (flags & 0x8000) == 0 {
461 self.mode = VMDAudioMode::U8;
463 fmt = SND_S16_FORMAT;
464 self.mode = VMDAudioMode::StereoDPCM;
465 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
468 fmt = SND_S16P_FORMAT;
469 self.blk_align = ainfo.get_block_len();
470 if (flags & 0x10) == 0 {
471 self.blk_size = (ainfo.get_block_len() + 1) * channels;
472 self.mode = VMDAudioMode::DPCM;
474 self.blk_size = ainfo.get_block_len() / 2 + 3;
475 self.mode = VMDAudioMode::ADPCM;
478 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
479 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo.clone()));
480 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
483 Err(DecoderError::InvalidData)
486 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
487 let info = pkt.get_stream().get_info();
488 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
489 let pktbuf = pkt.get_buffer();
490 validate!(pktbuf.len() >= 6);
491 let mut mr = MemoryReader::new_read(&pktbuf);
492 let mut br = ByteReader::new(&mut mr);
493 let blk_type = br.read_byte()?;
497 if blk_type == 2 { // initial
498 mask = br.read_u32le()?;
499 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
500 } else if blk_type == 3 { // silence
507 let mut samples = nblocks * self.blk_align;
508 if self.mode == VMDAudioMode::StereoDPCM && self.is_odd {
509 samples += (nblocks + if self.last_byte.is_some() { 1 } else { 0 }) / 2;
511 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
513 VMDAudioMode::DPCM => {
514 let mut adata = abuf.get_abuf_i16().unwrap();
515 let off1 = adata.get_offset(1);
516 let mut dst = adata.get_data_mut().unwrap();
517 self.decode_16bit(&mut dst, off1, &mut br, nblocks, mask)?;
519 VMDAudioMode::U8 => {
520 let mut adata = abuf.get_abuf_u8().unwrap();
521 let dst = adata.get_data_mut().unwrap();
524 let channels = self.chmap.num_channels();
525 for _ in 0..nblocks {
527 for i in 0..self.blk_align * channels {
530 } else if channels == 1 {
531 for i in 0..self.blk_size {
532 dst[doff + i] = br.read_byte()?;
535 for i in 0..self.blk_size {
536 let val = Self::cvt_u8(br.read_byte()?);
540 doff += self.blk_align * channels;
544 VMDAudioMode::StereoDPCM => {
545 let mut adata = abuf.get_abuf_i16().unwrap();
546 let dst = adata.get_data_mut().unwrap();
549 let mut ch = self.ch;
550 for _ in 0..nblocks {
551 let put_sample = self.last_byte.is_some();
552 if let (true, Some(val)) = (self.is_odd, self.last_byte) {
553 self.pred[ch] = Self::pred16(self.pred[ch], val);
554 dst[doff] = self.pred[ch] as i16;
557 self.last_byte = None;
560 for i in 0..self.blk_align {
561 dst[doff + i * 2 + 0] = self.pred[ch] as i16;
562 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
566 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
570 self.last_byte = Some(0);
574 for i in 0..self.blk_align {
575 self.pred[ch] = Self::pred16(self.pred[ch], br.read_byte()?);
576 dst[doff + i * 2] = self.pred[ch] as i16;
577 self.pred[ch ^ 1] = Self::pred16(self.pred[ch ^ 1], br.read_byte()?);
578 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
581 let val = br.read_byte()?;
583 self.pred[ch] = Self::pred16(self.pred[ch], val);
584 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
588 self.last_byte = Some(val);
592 doff += self.blk_align * 2;
597 VMDAudioMode::ADPCM => {
598 let mut adata = abuf.get_abuf_i16().unwrap();
599 let dst = adata.get_data_mut().unwrap();
601 if self.chmap.num_channels() == 1 {
603 let mut ima = IMAState::new();
604 for _ in 0..nblocks {
606 doff += (self.blk_size - 3) * 2;
610 let pred = br.read_u16le()? as i16;
611 let step = br.read_byte()?;
612 validate!((step as usize) < IMA_STEP_TABLE.len());
613 ima.reset(pred, step);
614 for _ in 3..self.blk_size {
615 let b = br.read_byte()?;
616 dst[doff] = ima.expand_sample(b >> 4);
618 dst[doff] = ima.expand_sample(b & 0xF);
624 return Err(DecoderError::InvalidData);
629 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
630 frm.set_duration(Some(samples as u64));
631 frm.set_keyframe(true);
634 Err(DecoderError::InvalidData)
637 fn flush(&mut self) {
641 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
642 Box::new(VMDAudioDecoder::new())
647 use nihav_core::codecs::RegisteredDecoders;
648 use nihav_core::demuxers::RegisteredDemuxers;
649 use nihav_codec_support::test::dec_video::*;
650 use crate::game_register_all_codecs;
651 use crate::game_register_all_demuxers;
653 fn test_vmd_video() {
654 let mut dmx_reg = RegisteredDemuxers::new();
655 game_register_all_demuxers(&mut dmx_reg);
656 let mut dec_reg = RegisteredDecoders::new();
657 game_register_all_codecs(&mut dec_reg);
659 test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
660 ExpectedTestResult::MD5Frames(vec![
661 [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
662 [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
663 [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
664 [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
665 [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
666 [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
667 [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
668 [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
669 [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
670 [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
671 [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
674 fn test_vmd_video_16bpp() {
675 let mut dmx_reg = RegisteredDemuxers::new();
676 game_register_all_demuxers(&mut dmx_reg);
677 let mut dec_reg = RegisteredDecoders::new();
678 game_register_all_codecs(&mut dec_reg);
680 test_decoding("vmd", "vmd-video", "assets/Game/HLP1000.VMD", Some(10), &dmx_reg, &dec_reg,
681 ExpectedTestResult::MD5Frames(vec![
682 [0x03d77d51, 0x8670ae24, 0x86184cc8, 0x9c928700],
683 [0xf4796f1b, 0x0f75a120, 0x62056509, 0xc83f1a2c],
684 [0xd9e6db4d, 0x7af82082, 0xac6a335c, 0x19b8438f],
685 [0x03d77d51, 0x8670ae24, 0x86184cc8, 0x9c928700],
686 [0xd9e6db4d, 0x7af82082, 0xac6a335c, 0x19b8438f],
687 [0xf4796f1b, 0x0f75a120, 0x62056509, 0xc83f1a2c]]));
690 fn test_vmd_video_24bpp() {
691 let mut dmx_reg = RegisteredDemuxers::new();
692 game_register_all_demuxers(&mut dmx_reg);
693 let mut dec_reg = RegisteredDecoders::new();
694 game_register_all_codecs(&mut dec_reg);
696 test_decoding("vmd", "vmd-video", "assets/Game/02C.VMD", None, &dmx_reg, &dec_reg,
697 ExpectedTestResult::MD5([0xb580782c, 0xd7fb98c0, 0xaf9b83cc, 0xaea0846b]));
700 fn test_vmd_audio_u8() {
701 let mut dmx_reg = RegisteredDemuxers::new();
702 game_register_all_demuxers(&mut dmx_reg);
703 let mut dec_reg = RegisteredDecoders::new();
704 game_register_all_codecs(&mut dec_reg);
706 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
707 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
710 fn test_vmd_audio_s16_old() {
711 let mut dmx_reg = RegisteredDemuxers::new();
712 game_register_all_demuxers(&mut dmx_reg);
713 let mut dec_reg = RegisteredDecoders::new();
714 game_register_all_codecs(&mut dec_reg);
716 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
717 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
720 fn test_vmd_audio_s16_new() {
721 let mut dmx_reg = RegisteredDemuxers::new();
722 game_register_all_demuxers(&mut dmx_reg);
723 let mut dec_reg = RegisteredDecoders::new();
724 game_register_all_codecs(&mut dec_reg);
726 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
727 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));
730 fn test_vmd_audio_ima_adpcm() {
731 let mut dmx_reg = RegisteredDemuxers::new();
732 game_register_all_demuxers(&mut dmx_reg);
733 let mut dec_reg = RegisteredDecoders::new();
734 game_register_all_codecs(&mut dec_reg);
736 test_decoding("vmd", "vmd-audio", "assets/Game/HLP1000.VMD", None, &dmx_reg, &dec_reg,
737 ExpectedTestResult::MD5([0x76a00405, 0xe4e5378d, 0x495b2a68, 0x4dffe042]));