let dst = &mut dst[dpos..][..len];
br.read_buf(dst)?;
} else {
- let val = br.read_byte()?;
- for i in 0..len {
- dst[dpos + i] = val;
+ let val1 = br.read_byte()?;
+ let val2 = br.read_byte()?;
+ for i in (0..len).step_by(2) {
+ dst[dpos + i] = val1;
+ dst[dpos + i + 1] = val2;
}
}
dpos += len;
buf: Vec<u8>,
width: usize,
height: usize,
+ xoff: usize,
+ yoff: usize,
hams: HAMShuffler,
}
buf: Vec::new(),
width: 0,
height: 0,
+ xoff: 0,
+ yoff: 0,
hams: HAMShuffler::default(),
}
}
if (frame_x == 0xFFFF) && (frame_y == 0xFFFF) && (frame_l == 0xFFFF) && (frame_d == 0xFFFF) {
return Ok(false);
}
+ validate!(frame_x >= self.xoff && frame_y >= self.yoff);
validate!(frame_l >= frame_x && frame_d >= frame_y);
- validate!(frame_l < self.width && frame_d < self.height);
+ validate!(frame_l - self.xoff < self.width && frame_d - self.yoff < self.height);
if has_pal {
br.read_skip(2)?;
let w = frame_l + 1 - frame_x;
let h = frame_d + 1 - frame_y;
- let dpos = frame_x + frame_y * stride;
+ let dpos = frame_x - self.xoff + (frame_y - self.yoff) * stride;
let method = br.read_byte()?;
let is_intra;
if let Some(ref edata) = info.get_extradata() {
validate!(edata.len() == 0x330);
let unp_size = read_u32le(&edata[800..])? as usize;
- validate!(unp_size < self.width * self.height * 3 + 64); // just for sanity
+ validate!(unp_size < self.width * self.height * 4 + 64); // just for sanity
self.buf.resize(unp_size, 0);
for i in 0..768 {
let el = edata[28 + i];
self.pal[i] = (el << 2) | (el >> 4);
}
+ self.xoff = read_u16le(&edata[8..])? as usize;
+ self.yoff = read_u16le(&edata[10..])? as usize;
}
Ok(())
}
}
fn cvt_u8(val: u8) -> u8 {
- if val < 128 {
- 127 - val
- } else {
- val
- }
+ val ^ 0x80
}
}
let mut dec_reg = RegisteredDecoders::new();
game_register_all_codecs(&mut dec_reg);
-// let file = "assets/Game/1491.VMD";
- let file = "assets/Game/128.vmd";
- test_file_decoding("vmd", file, Some(10), true, false, None/*Some("vmd")*/, &dmx_reg, &dec_reg);
+ test_decoding("vmd", "vmd-video", "assets/Game/2832.VMD", Some(10), &dmx_reg, &dec_reg,
+ ExpectedTestResult::MD5Frames(vec![
+ [0xd29e0214, 0xf38ad154, 0xccbd381f, 0x3de1109c],
+ [0x904074eb, 0x202b1d6f, 0xe3f68538, 0xf0db641c],
+ [0x9c8b1b6c, 0xe205b8dc, 0xbfb07406, 0x993ace41],
+ [0x71ce4220, 0x8747fd05, 0x854dd86d, 0x2664cde5],
+ [0x3bc65fa4, 0xebb95292, 0xe0a0fea6, 0x0acfdea1],
+ [0x33982045, 0x8d11b69b, 0xac254a75, 0x63896a21],
+ [0xa667db33, 0x90e122d3, 0x2243da15, 0xcc4bffd2],
+ [0x518621c1, 0xb91412bc, 0x12312869, 0x141ef647],
+ [0x3069977e, 0x68fd3fa0, 0x2bfdb00d, 0x1e694684],
+ [0x246c12aa, 0x15137fb0, 0xa4b0fc3e, 0x626a2676],
+ [0x72cce7e3, 0x98506d04, 0xd4d8bbaf, 0x3cc5e32d]]));
+ }
+ #[test]
+ fn test_vmd_audio_u8() {
+ let mut dmx_reg = RegisteredDemuxers::new();
+ game_register_all_demuxers(&mut dmx_reg);
+ let mut dec_reg = RegisteredDecoders::new();
+ game_register_all_codecs(&mut dec_reg);
+
+ test_decoding("vmd", "vmd-audio", "assets/Game/1491.VMD", None, &dmx_reg, &dec_reg,
+ ExpectedTestResult::MD5([0x75037601, 0xbc7b3976, 0x6e1c948b, 0xf05a3d6c]));
+ }
+ #[test]
+ fn test_vmd_audio_s16_old() {
+ let mut dmx_reg = RegisteredDemuxers::new();
+ game_register_all_demuxers(&mut dmx_reg);
+ let mut dec_reg = RegisteredDecoders::new();
+ game_register_all_codecs(&mut dec_reg);
+
+ test_decoding("vmd", "vmd-audio", "assets/Game/2832.VMD", None, &dmx_reg, &dec_reg,
+ ExpectedTestResult::MD5([0x32dcdf0e, 0xee058684, 0x43ed5bf1, 0x2ff18b5a]));
}
#[test]
- fn test_vmd_audio() {
+ fn test_vmd_audio_s16_new() {
let mut dmx_reg = RegisteredDemuxers::new();
game_register_all_demuxers(&mut dmx_reg);
let mut dec_reg = RegisteredDecoders::new();
game_register_all_codecs(&mut dec_reg);
-// let file = "assets/Game/1491.VMD";
- let file = "assets/Game/128.vmd";
-// let file = "assets/Game/1000.VMD";
-// let file = "assets/Game/235.VMD";
- test_decode_audio("vmd", file, None, None/*Some("vmd")*/, &dmx_reg, &dec_reg);
+ test_decoding("vmd", "vmd-audio", "assets/Game/1000.VMD", None, &dmx_reg, &dec_reg,
+ ExpectedTestResult::MD5([0xc36215d3, 0x96530a80, 0x89f1fa8e, 0x49da302b]));
}
}