arxel-vid: support 2-pixel tiles
[nihav.git] / nihav-game / src / codecs / arxel_vid.rs
index b2d6815d923ef18220d1245a5975916e46d2386b..d705c822c9281be4ec6681abea841e6ce5e43656 100644 (file)
@@ -8,7 +8,7 @@ const MV_2BIT: [(i8, i8); 4] = [(-1, 0), (-1, -1), (1, -1), (0, -2)];
 const MV_4BIT: [(i8, i8); 16] = [
     (-2, -3), ( 2, -3), (-1, -4), ( 1, -4),
     (-1, -2), ( 1, -2), ( 0, -3), ( 0, -4),
-    (-2,  0), (-2, -1), ( 1, -1), (-2, -2),
+    (-2,  0), (-2, -1), ( 2, -1), (-2, -2),
     ( 2, -2), (-1, -3), ( 1, -3), ( 0, -5)
 ];
 
@@ -71,21 +71,21 @@ impl NADecoder for ArxelVideoDecoder {
         validate!(height == vinfo.get_height());
 
                                               br.seek(SeekFrom::Start(part2_off + (HEADER_SIZE as u64)))?;
+        let tile_w = if tile_size == 2 { 2 } else { 4 };
+        let tsize = tile_w * BPP;
+
         match tile_size {
-            2 => {
-                return Err(DecoderError::NotImplemented);
-            },
-            4 => {
-                                              br.read_buf(&mut self.tiles[..16])?;
+            2 | 4 => {
+                                              br.read_buf(&mut self.tiles[..tsize])?;
                 let off = br.tell() as usize;
                 let mut bir = BitReader::new(&src[off..], BitReaderMode::BE);
                 for tile in 1..num_tiles {
-                    for i in 0..16 {
-                        self.tiles[tile * 16 + i] = self.tiles[tile * 16 + i - 16];
+                    for i in 0..tsize {
+                        self.tiles[tile * tsize + i] = self.tiles[tile * tsize + i - tsize];
                     }
                     let bits                = bir.read(3)? as u8 + 1;
                     validate!(bits < 8);
-                    for el in self.tiles[tile * 16..][..16].iter_mut() {
+                    for el in self.tiles[tile * tsize..][..tsize].iter_mut() {
                         let mut delta       = bir.read(bits)? as i16;
                         if delta != 0 && bir.read_bool()? {
                             delta = -delta;
@@ -95,7 +95,7 @@ impl NADecoder for ArxelVideoDecoder {
                 }
             },
             _ => {
-                validate!(tile_size > 0);
+                validate!(tile_size == num_tiles * tsize);
                                               br.read_buf(&mut self.tiles[..tile_size])?;
             },
         };
@@ -108,8 +108,6 @@ impl NADecoder for ArxelVideoDecoder {
         let dst = data.as_mut_slice();
 
         let mut br = BitReader::new(&src[HEADER_SIZE..], BitReaderMode::BE);
-        let tile_w = 4;
-        let tsize = tile_w * BPP;
         let idx_bits = if num_tiles < 0x400 { 10 } else if num_tiles < 0x800 { 11 } else { 12 };
         for y in (0..height).step_by(2) {
             for x in (0..width).step_by(tile_w) {
@@ -177,6 +175,6 @@ mod test {
         game_register_all_decoders(&mut dec_reg);
 
         test_decoding("arxel-cnm", "arxel-video", "assets/Game/logo.cnm", Some(10), &dmx_reg, &dec_reg,
-                      ExpectedTestResult::MD5([0xcf12f83a, 0xfdce1ed2, 0x2d183394, 0xa265f164]));
+                      ExpectedTestResult::MD5([0x9b1fc970, 0x1fe86e2c, 0x44dd9255, 0x3920c49b]));
     }
 }