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) {
338 impl NAOptionHandler for VMDVideoDecoder {
339 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
340 fn set_options(&mut self, _options: &[NAOption]) { }
341 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
345 pub fn get_decoder_video() -> Box<dyn NADecoder + Send> {
346 Box::new(VMDVideoDecoder::new())
349 #[derive(Clone,Copy,PartialEq)]
357 struct VMDAudioDecoder {
359 info: Arc<NACodecInfo>,
365 last_byte: Option<u8>,
370 const SOL_AUD_STEPS16: [i16; 128] = [
371 0x00, 0x08, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60,
372 0x70, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0,
373 0xF0, 0x100, 0x110, 0x120, 0x130, 0x140, 0x150, 0x160,
374 0x170, 0x180, 0x190, 0x1A0, 0x1B0, 0x1C0, 0x1D0, 0x1E0,
375 0x1F0, 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230,
376 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270,
377 0x278, 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0,
378 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0,
379 0x2F8, 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330,
380 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370,
381 0x378, 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, 0x3B0,
382 0x3B8, 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, 0x3F0,
383 0x3F8, 0x400, 0x440, 0x480, 0x4C0, 0x500, 0x540, 0x580,
384 0x5C0, 0x600, 0x640, 0x680, 0x6C0, 0x700, 0x740, 0x780,
385 0x7C0, 0x800, 0x900, 0xA00, 0xB00, 0xC00, 0xD00, 0xE00,
386 0xF00, 0x1000, 0x1400, 0x1800, 0x1C00, 0x2000, 0x3000, 0x4000
389 impl VMDAudioDecoder {
392 ainfo: NAAudioInfo::new(0, 1, SND_S16P_FORMAT, 0),
393 info: NACodecInfo::new_dummy(),
394 chmap: NAChannelMap::new(),
397 mode: VMDAudioMode::U8,
404 fn decode_16bit(&self, dst: &mut [i16], off1: usize, br: &mut ByteReader, nblocks: usize, mut mask: u32) -> DecoderResult<()> {
405 let channels = self.chmap.num_channels();
406 let mut off = [0, off1];
407 for _ in 0..nblocks {
409 for ch in 0..channels {
410 for i in 0..self.blk_align {
411 dst[off[ch] + i] = 0;
413 off[ch] += self.blk_align;
416 let mut pred: [i32; 2] = [0; 2];
417 for ch in 0..channels {
418 pred[ch] = i32::from(br.read_u16le()?);
419 dst[off[ch]] = pred[ch] as i16;
423 let flip_ch = if channels == 2 { 1 } else { 0 };
424 for _ in channels..self.blk_align*channels {
425 pred[ch] = Self::pred16(pred[ch], br.read_byte()?);
426 //pred[ch] = pred[ch].max(-32768).min(32767);
427 dst[off[ch]] = pred[ch] as i16;
434 validate!(br.left() == 0);
437 fn pred16(pred: i32, val: u8) -> i32 {
438 if (val & 0x80) != 0 {
439 pred - i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
441 pred + i32::from(SOL_AUD_STEPS16[(val & 0x7F) as usize])
446 impl NADecoder for VMDAudioDecoder {
447 fn init(&mut self, _supp: &mut NADecoderSupport, info: NACodecInfoRef) -> DecoderResult<()> {
448 if let NACodecTypeInfo::Audio(ainfo) = info.get_properties() {
450 let channels = ainfo.get_channels() as usize;
451 let edata = info.get_extradata();
452 let flags = if let Some(ref buf) = edata {
453 validate!(buf.len() >= 2);
454 u16::from(buf[0]) | (u16::from(buf[1]) << 8)
458 validate!((channels == 1) ^ ((flags & 0x8200) != 0));
459 if ainfo.get_format().get_bits() == 8 {
460 self.blk_size = ainfo.get_block_len();
461 self.blk_align = ainfo.get_block_len() / channels;
462 if (flags & 0x8000) == 0 {
464 self.mode = VMDAudioMode::U8;
466 fmt = SND_S16_FORMAT;
467 self.mode = VMDAudioMode::StereoDPCM;
468 self.is_odd = (channels == 2) && ((self.blk_size & 1) != 0);
471 self.blk_align = ainfo.get_block_len();
472 if (flags & 0x10) == 0 {
473 fmt = SND_S16P_FORMAT;
474 self.blk_size = (ainfo.get_block_len() + 1) * channels;
475 self.mode = VMDAudioMode::DPCM;
477 fmt = SND_S16_FORMAT;
478 self.blk_size = (ainfo.get_block_len() * channels + 1) / 2 + 3 * channels;
479 self.mode = VMDAudioMode::ADPCM;
482 self.ainfo = NAAudioInfo::new(ainfo.get_sample_rate(), ainfo.get_channels(), fmt, ainfo.get_block_len());
483 self.info = info.replace_info(NACodecTypeInfo::Audio(self.ainfo));
484 self.chmap = NAChannelMap::from_str(if channels == 1 { "C" } else { "L,R" }).unwrap();
487 Err(DecoderError::InvalidData)
490 #[allow(clippy::identity_op)]
491 #[allow(clippy::cognitive_complexity)]
492 fn decode(&mut self, _supp: &mut NADecoderSupport, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
493 let info = pkt.get_stream().get_info();
494 if let NACodecTypeInfo::Audio(_) = info.get_properties() {
495 let pktbuf = pkt.get_buffer();
496 validate!(pktbuf.len() >= 6);
497 let mut mr = MemoryReader::new_read(&pktbuf);
498 let mut br = ByteReader::new(&mut mr);
499 let blk_type = br.read_byte()?;
503 if blk_type == 2 { // initial
504 mask = br.read_u32le()?;
505 nblocks = (mask.count_ones() as usize) + (pktbuf.len() - 14) / self.blk_size;
506 } else if blk_type == 3 { // silence
513 let mut samples = nblocks * self.blk_align;
514 if self.mode == VMDAudioMode::StereoDPCM && self.is_odd {
515 samples += (nblocks + if self.last_byte.is_some() { 1 } else { 0 }) / 2;
517 let abuf = alloc_audio_buffer(self.ainfo, samples, self.chmap.clone())?;
519 VMDAudioMode::DPCM => {
520 let mut adata = abuf.get_abuf_i16().unwrap();
521 let off1 = adata.get_offset(1);
522 let dst = adata.get_data_mut().unwrap();
523 self.decode_16bit(dst, off1, &mut br, nblocks, mask)?;
525 VMDAudioMode::U8 => {
526 let mut adata = abuf.get_abuf_u8().unwrap();
527 let dst = adata.get_data_mut().unwrap();
530 let channels = self.chmap.num_channels();
531 for _ in 0..nblocks {
533 for i in 0..self.blk_align * channels {
536 } else if channels == 1 {
537 for i in 0..self.blk_size {
538 dst[doff + i] = br.read_byte()?;
543 doff += self.blk_align * channels;
547 VMDAudioMode::StereoDPCM => {
548 let mut adata = abuf.get_abuf_i16().unwrap();
549 let dst = adata.get_data_mut().unwrap();
552 let mut ch = self.ch;
553 for _ in 0..nblocks {
554 let put_sample = self.last_byte.is_some();
555 if let (true, Some(val)) = (self.is_odd, self.last_byte) {
556 self.pred[ch] = Self::pred16(self.pred[ch], val);
557 dst[doff] = self.pred[ch] as i16;
560 self.last_byte = None;
563 for i in 0..self.blk_align {
564 dst[doff + i * 2 + 0] = self.pred[ch] as i16;
565 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
569 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
573 self.last_byte = Some(0);
577 for i in 0..self.blk_align {
578 self.pred[ch] = Self::pred16(self.pred[ch], br.read_byte()?);
579 dst[doff + i * 2] = self.pred[ch] as i16;
580 self.pred[ch ^ 1] = Self::pred16(self.pred[ch ^ 1], br.read_byte()?);
581 dst[doff + i * 2 + 1] = self.pred[ch ^ 1] as i16;
584 let val = br.read_byte()?;
586 self.pred[ch] = Self::pred16(self.pred[ch], val);
587 dst[doff + self.blk_align * 2] = self.pred[ch] as i16;
591 self.last_byte = Some(val);
595 doff += self.blk_align * 2;
600 VMDAudioMode::ADPCM => {
601 let mut adata = abuf.get_abuf_i16().unwrap();
602 let dst = adata.get_data_mut().unwrap();
604 if self.chmap.num_channels() == 1 {
606 let mut ima = IMAState::new();
607 for _ in 0..nblocks {
609 for i in 0..self.blk_align {
612 doff += self.blk_align;
616 let pred = br.read_u16le()? as i16;
617 let step = br.read_byte()?;
618 validate!((step as usize) < IMA_STEP_TABLE.len());
619 ima.reset(pred, step);
621 for i in 0..self.blk_align {
624 dst[doff] = ima.expand_sample(b >> 4);
626 dst[doff] = ima.expand_sample(b & 0xF);
634 let mut ima1 = IMAState::new();
635 let mut ima2 = IMAState::new();
636 for _ in 0..nblocks {
638 for i in 0..self.blk_align * 2 {
641 doff += self.blk_align * 2;
645 let pred1 = br.read_u16le()? as i16;
646 let pred2 = br.read_u16le()? as i16;
647 let step1 = br.read_byte()?;
648 let step2 = br.read_byte()?;
649 validate!((step1 as usize) < IMA_STEP_TABLE.len());
650 validate!((step2 as usize) < IMA_STEP_TABLE.len());
651 ima1.reset(pred1, step1);
652 ima2.reset(pred2, step2);
653 for _ in 0..self.blk_align {
654 let b = br.read_byte()?;
655 dst[doff] = ima1.expand_sample(b >> 4);
657 dst[doff] = ima2.expand_sample(b & 0xF);
666 let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone(), abuf);
667 frm.set_duration(Some(samples as u64));
668 frm.set_keyframe(true);
671 Err(DecoderError::InvalidData)
674 fn flush(&mut self) {
678 impl NAOptionHandler for VMDAudioDecoder {
679 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
680 fn set_options(&mut self, _options: &[NAOption]) { }
681 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
684 pub fn get_decoder_audio() -> Box<dyn NADecoder + Send> {
685 Box::new(VMDAudioDecoder::new())
690 use nihav_core::codecs::RegisteredDecoders;
691 use nihav_core::demuxers::RegisteredDemuxers;
692 use nihav_codec_support::test::dec_video::*;
693 use crate::game_register_all_decoders;
694 use crate::game_register_all_demuxers;
695 // samples from https://samples.mplayerhq.hu/game-formats/sierra-vmd/ and various games
697 fn test_vmd_video() {
698 let mut dmx_reg = RegisteredDemuxers::new();
699 game_register_all_demuxers(&mut dmx_reg);
700 let mut dec_reg = RegisteredDecoders::new();
701 game_register_all_decoders(&mut dec_reg);
703 test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
704 ExpectedTestResult::MD5Frames(vec![
705 [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
706 [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
707 [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
708 [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
709 [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
710 [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
711 [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
712 [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
713 [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
714 [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
715 [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
718 fn test_vmd_video_16bpp() {
719 let mut dmx_reg = RegisteredDemuxers::new();
720 game_register_all_demuxers(&mut dmx_reg);
721 let mut dec_reg = RegisteredDecoders::new();
722 game_register_all_decoders(&mut dec_reg);
724 test_decoding("vmd", "vmd-video", "assets/Game/HLP1000.VMD", Some(10), &dmx_reg, &dec_reg,
725 ExpectedTestResult::MD5Frames(vec![
726 [0x03d77d51, 0x8670ae24, 0x86184cc8, 0x9c928700],
727 [0xf4796f1b, 0x0f75a120, 0x62056509, 0xc83f1a2c],
728 [0xd9e6db4d, 0x7af82082, 0xac6a335c, 0x19b8438f],
729 [0x03d77d51, 0x8670ae24, 0x86184cc8, 0x9c928700],
730 [0xd9e6db4d, 0x7af82082, 0xac6a335c, 0x19b8438f],
731 [0xf4796f1b, 0x0f75a120, 0x62056509, 0xc83f1a2c]]));
734 fn test_vmd_video_24bpp() {
735 let mut dmx_reg = RegisteredDemuxers::new();
736 game_register_all_demuxers(&mut dmx_reg);
737 let mut dec_reg = RegisteredDecoders::new();
738 game_register_all_decoders(&mut dec_reg);
740 test_decoding("vmd", "vmd-video", "assets/Game/02C.VMD", None, &dmx_reg, &dec_reg,
741 ExpectedTestResult::MD5([0xb580782c, 0xd7fb98c0, 0xaf9b83cc, 0xaea0846b]));
744 fn test_vmd_audio_u8() {
745 let mut dmx_reg = RegisteredDemuxers::new();
746 game_register_all_demuxers(&mut dmx_reg);
747 let mut dec_reg = RegisteredDecoders::new();
748 game_register_all_decoders(&mut dec_reg);
750 test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
751 ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
754 fn test_vmd_audio_s16_old() {
755 let mut dmx_reg = RegisteredDemuxers::new();
756 game_register_all_demuxers(&mut dmx_reg);
757 let mut dec_reg = RegisteredDecoders::new();
758 game_register_all_decoders(&mut dec_reg);
760 test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
761 ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
764 fn test_vmd_audio_s16_new() {
765 let mut dmx_reg = RegisteredDemuxers::new();
766 game_register_all_demuxers(&mut dmx_reg);
767 let mut dec_reg = RegisteredDecoders::new();
768 game_register_all_decoders(&mut dec_reg);
770 test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
771 ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));
774 fn test_vmd_audio_ima_adpcm() {
775 let mut dmx_reg = RegisteredDemuxers::new();
776 game_register_all_demuxers(&mut dmx_reg);
777 let mut dec_reg = RegisteredDecoders::new();
778 game_register_all_decoders(&mut dec_reg);
780 test_decoding("vmd", "vmd-audio", "assets/Game/HLP1000.VMD", None, &dmx_reg, &dec_reg,
781 ExpectedTestResult::MD5([0x76a00405, 0xe4e5378d, 0x495b2a68, 0x4dffe042]));