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