std/vp8: parse the residuals

This commit, part of a series, is inspired by pull request PR #168 by
Damian Kaczmarek (with AI assistance), with some modifications.

Updates PR #168
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 6930981..36822c2 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -15529,10 +15529,9 @@
     uint32_t f_quant_y2ac_delta;
     uint32_t f_quant_uvdc_delta;
     uint32_t f_quant_uvac_delta;
+    uint16_t f_dequants[4][3][2];
     uint32_t f_prob_skip;
     uint8_t f_mb_subblock_modes[16];
-    uint8_t f_mb_left_modes[4];
-    uint8_t f_mb_top_modes[1024][4];
     uint32_t f_dst_x;
     uint32_t f_dst_y;
     wuffs_base__pixel_swizzler f_swizzler;
@@ -15548,6 +15547,9 @@
 
   struct {
     uint8_t f_coeff_probs[1056];
+    uint16_t f_mb_coeffs[25][16];
+    uint32_t f_mb_states_left;
+    uint32_t f_mb_states_top[1024];
 
     struct {
       uint64_t v_i;
@@ -80968,6 +80970,12 @@
 };
 
 static const uint8_t
+WUFFS_VP8__CLIP_9[16] WUFFS_BASE__POTENTIALLY_UNUSED = {
+  0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u,
+  8u, 9u, 9u, 9u, 9u, 9u, 9u, 9u,
+};
+
+static const uint8_t
 WUFFS_VP8__SUBBLOCK_MODE_PROBS[10][10][9] WUFFS_BASE__POTENTIALLY_UNUSED = {
   {
     {
@@ -81304,6 +81312,30 @@
 };
 
 static const uint8_t
+WUFFS_VP8__CATEGORY_PROBS[4][16] WUFFS_BASE__POTENTIALLY_UNUSED = {
+  {
+    173u, 148u, 140u, 0u, 0u, 0u, 0u, 0u,
+    0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
+  }, {
+    176u, 155u, 140u, 135u, 0u, 0u, 0u, 0u,
+    0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
+  }, {
+    180u, 157u, 141u, 134u, 130u, 0u, 0u, 0u,
+    0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
+  }, {
+    254u, 254u, 243u, 230u, 196u, 177u, 153u, 140u,
+    133u, 130u, 129u, 0u, 0u, 0u, 0u, 0u,
+  },
+};
+
+static const uint32_t
+WUFFS_VP8__COEFF_BANDS_33[17] WUFFS_BASE__POTENTIALLY_UNUSED = {
+  0u, 33u, 66u, 99u, 198u, 132u, 165u, 198u,
+  198u, 198u, 198u, 198u, 198u, 198u, 198u, 231u,
+  0u,
+};
+
+static const uint8_t
 WUFFS_VP8__COEFF_UPDATE_PROBS[1056] WUFFS_BASE__POTENTIALLY_UNUSED = {
   255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u,
   255u, 255u, 255u, 255u, 255u, 255u, 255u, 255u,
@@ -81575,6 +81607,51 @@
   128u, 128u, 128u, 128u, 128u, 128u, 128u, 128u,
 };
 
+static const uint16_t
+WUFFS_VP8__DEQUANTS[2][128] WUFFS_BASE__POTENTIALLY_UNUSED = {
+  {
+    4u, 5u, 6u, 7u, 8u, 9u, 10u, 10u,
+    11u, 12u, 13u, 14u, 15u, 16u, 17u, 17u,
+    18u, 19u, 20u, 20u, 21u, 21u, 22u, 22u,
+    23u, 23u, 24u, 25u, 25u, 26u, 27u, 28u,
+    29u, 30u, 31u, 32u, 33u, 34u, 35u, 36u,
+    37u, 37u, 38u, 39u, 40u, 41u, 42u, 43u,
+    44u, 45u, 46u, 46u, 47u, 48u, 49u, 50u,
+    51u, 52u, 53u, 54u, 55u, 56u, 57u, 58u,
+    59u, 60u, 61u, 62u, 63u, 64u, 65u, 66u,
+    67u, 68u, 69u, 70u, 71u, 72u, 73u, 74u,
+    75u, 76u, 76u, 77u, 78u, 79u, 80u, 81u,
+    82u, 83u, 84u, 85u, 86u, 87u, 88u, 89u,
+    91u, 93u, 95u, 96u, 98u, 100u, 101u, 102u,
+    104u, 106u, 108u, 110u, 112u, 114u, 116u, 118u,
+    122u, 124u, 126u, 128u, 130u, 132u, 134u, 136u,
+    138u, 140u, 143u, 145u, 148u, 151u, 154u, 157u,
+  }, {
+    4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u,
+    12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u,
+    20u, 21u, 22u, 23u, 24u, 25u, 26u, 27u,
+    28u, 29u, 30u, 31u, 32u, 33u, 34u, 35u,
+    36u, 37u, 38u, 39u, 40u, 41u, 42u, 43u,
+    44u, 45u, 46u, 47u, 48u, 49u, 50u, 51u,
+    52u, 53u, 54u, 55u, 56u, 57u, 58u, 60u,
+    62u, 64u, 66u, 68u, 70u, 72u, 74u, 76u,
+    78u, 80u, 82u, 84u, 86u, 88u, 90u, 92u,
+    94u, 96u, 98u, 100u, 102u, 104u, 106u, 108u,
+    110u, 112u, 114u, 116u, 119u, 122u, 125u, 128u,
+    131u, 134u, 137u, 140u, 143u, 146u, 149u, 152u,
+    155u, 158u, 161u, 164u, 167u, 170u, 173u, 177u,
+    181u, 185u, 189u, 193u, 197u, 201u, 205u, 209u,
+    213u, 217u, 221u, 225u, 229u, 234u, 239u, 245u,
+    249u, 254u, 259u, 264u, 269u, 274u, 279u, 284u,
+  },
+};
+
+static const uint8_t
+WUFFS_VP8__ZIGZAG[16] WUFFS_BASE__POTENTIALLY_UNUSED = {
+  0u, 1u, 4u, 8u, 5u, 2u, 3u, 6u,
+  9u, 12u, 13u, 10u, 7u, 11u, 14u, 15u,
+};
+
 // ---------------- Private Initializer Prototypes
 
 // ---------------- Private Function Prototypes
@@ -81635,6 +81712,17 @@
     wuffs_base__slice_u8 a_workbuf);
 
 WUFFS_BASE__GENERATED_C_CODE
+static wuffs_base__empty_struct
+wuffs_vp8__decoder__calculate_dequants(
+    wuffs_vp8__decoder* self);
+
+WUFFS_BASE__GENERATED_C_CODE
+static uint32_t
+wuffs_vp8__decoder__clip_127(
+    const wuffs_vp8__decoder* self,
+    uint32_t a_a);
+
+WUFFS_BASE__GENERATED_C_CODE
 static wuffs_base__status
 wuffs_vp8__decoder__decode_other_partition_lengths(
     wuffs_vp8__decoder* self,
@@ -81683,6 +81771,41 @@
     uint8_t a_left_mode);
 
 WUFFS_BASE__GENERATED_C_CODE
+static wuffs_base__empty_struct
+wuffs_vp8__decoder__decode_residuals(
+    wuffs_vp8__decoder* self,
+    wuffs_base__slice_u8 a_workbuf,
+    uint32_t a_mbx,
+    uint32_t a_mby,
+    uint32_t a_seg,
+    uint32_t a_luma_mode,
+    uint32_t a_chroma_mode);
+
+WUFFS_BASE__GENERATED_C_CODE
+static wuffs_base__empty_struct
+wuffs_vp8__decoder__initialize_mb_coeffs(
+    wuffs_vp8__decoder* self);
+
+WUFFS_BASE__GENERATED_C_CODE
+static uint32_t
+wuffs_vp8__decoder__decode_block_coefficients(
+    wuffs_vp8__decoder* self,
+    wuffs_base__slice_u8 a_workbuf,
+    uint32_t a_mby,
+    uint32_t a_seg,
+    uint32_t a_b,
+    uint32_t a_plane,
+    uint32_t a_context);
+
+WUFFS_BASE__GENERATED_C_CODE
+static uint32_t
+wuffs_vp8__decoder__decode_large_value(
+    wuffs_vp8__decoder* self,
+    wuffs_base__slice_u8 a_workbuf,
+    uint32_t a_part,
+    uint32_t a_prob_base);
+
+WUFFS_BASE__GENERATED_C_CODE
 static wuffs_base__status
 wuffs_vp8__decoder__do_decode_image_config(
     wuffs_vp8__decoder* self,
@@ -82010,6 +82133,7 @@
   self->private_impl.f_quant_y2ac_delta = wuffs_vp8__decoder__read_signed(self, a_workbuf, 0u, 4u);
   self->private_impl.f_quant_uvdc_delta = wuffs_vp8__decoder__read_signed(self, a_workbuf, 0u, 4u);
   self->private_impl.f_quant_uvac_delta = wuffs_vp8__decoder__read_signed(self, a_workbuf, 0u, 4u);
+  wuffs_vp8__decoder__calculate_dequants(self);
   if ( ! self->private_impl.f_is_key_frame) {
     return wuffs_base__make_status(wuffs_vp8__error__unsupported_vp8_file);
   }
@@ -82139,6 +82263,56 @@
   return wuffs_base__make_empty_struct();
 }
 
+// -------- func vp8.decoder.calculate_dequants
+
+WUFFS_BASE__GENERATED_C_CODE
+static wuffs_base__empty_struct
+wuffs_vp8__decoder__calculate_dequants(
+    wuffs_vp8__decoder* self) {
+  uint32_t v_seg = 0;
+  uint32_t v_q = 0;
+
+  v_seg = 0u;
+  while (v_seg < 4u) {
+    v_q = self->private_impl.f_quant_yac_qi;
+    if ( ! self->private_impl.f_seg_enabled) {
+    } else if (self->private_impl.f_seg_absolute) {
+      v_q = wuffs_base__utility__sign_extend_convert_u8_u32(self->private_impl.f_seg_quants[v_seg]);
+    } else {
+      v_q += wuffs_base__utility__sign_extend_convert_u8_u32(self->private_impl.f_seg_quants[v_seg]);
+    }
+    self->private_impl.f_dequants[v_seg][0u][0u] = WUFFS_VP8__DEQUANTS[0u][wuffs_vp8__decoder__clip_127(self, ((uint32_t)(v_q + self->private_impl.f_quant_ydc_delta)))];
+    self->private_impl.f_dequants[v_seg][0u][1u] = WUFFS_VP8__DEQUANTS[1u][wuffs_vp8__decoder__clip_127(self, v_q)];
+    self->private_impl.f_dequants[v_seg][1u][0u] = ((uint16_t)(WUFFS_VP8__DEQUANTS[0u][wuffs_vp8__decoder__clip_127(self, ((uint32_t)(v_q + self->private_impl.f_quant_y2dc_delta)))] * 2u));
+    self->private_impl.f_dequants[v_seg][1u][1u] = ((uint16_t)(((uint16_t)(WUFFS_VP8__DEQUANTS[1u][wuffs_vp8__decoder__clip_127(self, ((uint32_t)(v_q + self->private_impl.f_quant_y2ac_delta)))] * 155u)) / 100u));
+    if (self->private_impl.f_dequants[v_seg][1u][1u] < 8u) {
+      self->private_impl.f_dequants[v_seg][1u][1u] = 8u;
+    }
+    self->private_impl.f_dequants[v_seg][2u][0u] = WUFFS_VP8__DEQUANTS[0u][wuffs_vp8__decoder__clip_127(self, ((uint32_t)(v_q + self->private_impl.f_quant_uvdc_delta)))];
+    if (self->private_impl.f_dequants[v_seg][2u][0u] > 132u) {
+      self->private_impl.f_dequants[v_seg][2u][0u] = 132u;
+    }
+    self->private_impl.f_dequants[v_seg][2u][1u] = WUFFS_VP8__DEQUANTS[1u][wuffs_vp8__decoder__clip_127(self, ((uint32_t)(v_q + self->private_impl.f_quant_uvac_delta)))];
+    v_seg += 1u;
+  }
+  return wuffs_base__make_empty_struct();
+}
+
+// -------- func vp8.decoder.clip_127
+
+WUFFS_BASE__GENERATED_C_CODE
+static uint32_t
+wuffs_vp8__decoder__clip_127(
+    const wuffs_vp8__decoder* self,
+    uint32_t a_a) {
+  if (a_a >= 2147483648u) {
+    return 0u;
+  } else if (a_a >= 127u) {
+    return 127u;
+  }
+  return a_a;
+}
+
 // -------- func vp8.decoder.decode_other_partition_lengths
 
 WUFFS_BASE__GENERATED_C_CODE
@@ -82207,18 +82381,12 @@
 
   v_mbx = 0u;
   while (v_mbx < self->private_impl.f_mbw) {
-    self->private_impl.f_mb_top_modes[v_mbx][0u] = 0u;
-    self->private_impl.f_mb_top_modes[v_mbx][1u] = 0u;
-    self->private_impl.f_mb_top_modes[v_mbx][2u] = 0u;
-    self->private_impl.f_mb_top_modes[v_mbx][3u] = 0u;
+    self->private_data.f_mb_states_top[v_mbx] = 0u;
     v_mbx += 1u;
   }
   v_mby = 0u;
   while (v_mby < self->private_impl.f_mbh) {
-    self->private_impl.f_mb_left_modes[0u] = 0u;
-    self->private_impl.f_mb_left_modes[1u] = 0u;
-    self->private_impl.f_mb_left_modes[2u] = 0u;
-    self->private_impl.f_mb_left_modes[3u] = 0u;
+    self->private_data.f_mb_states_left = 0u;
     v_mbx = 0u;
     while (v_mbx < self->private_impl.f_mbw) {
       wuffs_vp8__decoder__decode_one_macroblock(self, a_workbuf, v_mbx, v_mby);
@@ -82264,6 +82432,16 @@
   wuffs_vp8__decoder__decode_subblock_modes(self, a_workbuf, a_mbx, v_luma_mode);
   v_chroma_mode = wuffs_vp8__decoder__decode_chroma_mode(self, a_workbuf);
   if (v_skip) {
+    self->private_data.f_mb_states_left &= 65535u;
+    self->private_data.f_mb_states_top[a_mbx] &= 65535u;
+  } else {
+    wuffs_vp8__decoder__decode_residuals(self,
+        a_workbuf,
+        a_mbx,
+        a_mby,
+        v_seg,
+        v_luma_mode,
+        v_chroma_mode);
   }
   return wuffs_base__make_empty_struct();
 }
@@ -82326,25 +82504,19 @@
   uint8_t v_mode = 0;
 
   if (a_luma_mode < 4u) {
-    self->private_impl.f_mb_top_modes[a_mbx][0u] = v_mode;
-    self->private_impl.f_mb_top_modes[a_mbx][1u] = v_mode;
-    self->private_impl.f_mb_top_modes[a_mbx][2u] = v_mode;
-    self->private_impl.f_mb_top_modes[a_mbx][3u] = v_mode;
-    self->private_impl.f_mb_left_modes[0u] = v_mode;
-    self->private_impl.f_mb_left_modes[1u] = v_mode;
-    self->private_impl.f_mb_left_modes[2u] = v_mode;
-    self->private_impl.f_mb_left_modes[3u] = v_mode;
+    self->private_data.f_mb_states_top[a_mbx] = (((uint32_t)(v_mode)) * 4369u);
+    self->private_data.f_mb_states_left = (((uint32_t)(v_mode)) * 4369u);
     return wuffs_base__make_empty_struct();
   }
   v_i = 0u;
   while (v_i < 16u) {
     if (v_i < 4u) {
-      v_top_mode = self->private_impl.f_mb_top_modes[a_mbx][v_i];
+      v_top_mode = WUFFS_VP8__CLIP_9[(15u & (self->private_data.f_mb_states_top[a_mbx] >> (v_i * 4u)))];
     } else {
       v_top_mode = self->private_impl.f_mb_subblock_modes[(v_i - 4u)];
     }
     if ((v_i & 3u) == 0u) {
-      v_left_mode = self->private_impl.f_mb_left_modes[(v_i >> 2u)];
+      v_left_mode = WUFFS_VP8__CLIP_9[(15u & (self->private_data.f_mb_states_left >> (v_i & 12u)))];
     } else {
       v_left_mode = self->private_impl.f_mb_subblock_modes[(((uint32_t)(v_i + 15u)) & 15u)];
     }
@@ -82352,14 +82524,16 @@
     self->private_impl.f_mb_subblock_modes[v_i] = v_mode;
     v_i += 1u;
   }
-  self->private_impl.f_mb_top_modes[a_mbx][0u] = self->private_impl.f_mb_subblock_modes[12u];
-  self->private_impl.f_mb_top_modes[a_mbx][1u] = self->private_impl.f_mb_subblock_modes[13u];
-  self->private_impl.f_mb_top_modes[a_mbx][2u] = self->private_impl.f_mb_subblock_modes[14u];
-  self->private_impl.f_mb_top_modes[a_mbx][3u] = self->private_impl.f_mb_subblock_modes[15u];
-  self->private_impl.f_mb_left_modes[0u] = self->private_impl.f_mb_subblock_modes[3u];
-  self->private_impl.f_mb_left_modes[1u] = self->private_impl.f_mb_subblock_modes[7u];
-  self->private_impl.f_mb_left_modes[2u] = self->private_impl.f_mb_subblock_modes[11u];
-  self->private_impl.f_mb_left_modes[3u] = self->private_impl.f_mb_subblock_modes[15u];
+  self->private_data.f_mb_states_top[a_mbx] = ((self->private_data.f_mb_states_top[a_mbx] & 4294901760u) |
+      (((uint32_t)(self->private_impl.f_mb_subblock_modes[12u])) << 0u) |
+      (((uint32_t)(self->private_impl.f_mb_subblock_modes[13u])) << 4u) |
+      (((uint32_t)(self->private_impl.f_mb_subblock_modes[14u])) << 8u) |
+      (((uint32_t)(self->private_impl.f_mb_subblock_modes[15u])) << 12u));
+  self->private_data.f_mb_states_left = ((self->private_data.f_mb_states_left & 4294901760u) |
+      (((uint32_t)(self->private_impl.f_mb_subblock_modes[3u])) << 0u) |
+      (((uint32_t)(self->private_impl.f_mb_subblock_modes[7u])) << 4u) |
+      (((uint32_t)(self->private_impl.f_mb_subblock_modes[11u])) << 8u) |
+      (((uint32_t)(self->private_impl.f_mb_subblock_modes[15u])) << 12u));
   return wuffs_base__make_empty_struct();
 }
 
@@ -82417,6 +82591,245 @@
   return 9u;
 }
 
+// -------- func vp8.decoder.decode_residuals
+
+WUFFS_BASE__GENERATED_C_CODE
+static wuffs_base__empty_struct
+wuffs_vp8__decoder__decode_residuals(
+    wuffs_vp8__decoder* self,
+    wuffs_base__slice_u8 a_workbuf,
+    uint32_t a_mbx,
+    uint32_t a_mby,
+    uint32_t a_seg,
+    uint32_t a_luma_mode,
+    uint32_t a_chroma_mode) {
+  uint32_t v_bc = 0;
+  uint32_t v_by = 0;
+  uint32_t v_bx = 0;
+  uint32_t v_plane = 0;
+  uint32_t v_lnz = 0;
+  uint32_t v_tnz = 0;
+
+  wuffs_vp8__decoder__initialize_mb_coeffs(self);
+  v_plane = 3u;
+  if (a_luma_mode < 4u) {
+    v_lnz = (1u & (self->private_data.f_mb_states_left >> 23u));
+    self->private_data.f_mb_states_left &= 4286578687u;
+    v_tnz = (1u & (self->private_data.f_mb_states_top[a_mbx] >> 23u));
+    self->private_data.f_mb_states_top[a_mbx] &= 4286578687u;
+    v_lnz = wuffs_vp8__decoder__decode_block_coefficients(self,
+        a_workbuf,
+        a_mby,
+        a_seg,
+        24u,
+        1u,
+        (v_lnz + v_tnz));
+    self->private_data.f_mb_states_top[a_mbx] |= (v_lnz << 23u);
+    self->private_data.f_mb_states_left |= (v_lnz << 23u);
+    v_plane = 0u;
+  }
+  v_by = 0u;
+  while (v_by < 4u) {
+    v_lnz = (1u & (self->private_data.f_mb_states_left >> (24u + v_by)));
+    self->private_data.f_mb_states_left &= (4294967295u ^ (((uint32_t)(1u)) << (24u + v_by)));
+    v_bx = 0u;
+    while (v_bx < 4u) {
+      v_tnz = (1u & (self->private_data.f_mb_states_top[a_mbx] >> (24u + v_bx)));
+      self->private_data.f_mb_states_top[a_mbx] &= (4294967295u ^ (((uint32_t)(1u)) << (24u + v_bx)));
+      v_lnz = wuffs_vp8__decoder__decode_block_coefficients(self,
+          a_workbuf,
+          a_mby,
+          a_seg,
+          ((4u * v_by) + v_bx),
+          v_plane,
+          (v_lnz + v_tnz));
+      self->private_data.f_mb_states_top[a_mbx] |= (v_lnz << (24u + v_bx));
+      v_bx += 1u;
+    }
+    self->private_data.f_mb_states_left |= (v_lnz << (24u + v_by));
+    v_by += 1u;
+  }
+  v_bc = 0u;
+  while (v_bc <= 2u) {
+    v_by = 0u;
+    while (v_by < 2u) {
+      v_lnz = (1u & (self->private_data.f_mb_states_left >> (28u + v_bc + v_by)));
+      self->private_data.f_mb_states_left &= (4294967295u ^ (((uint32_t)(1u)) << (28u + v_bc + v_by)));
+      v_bx = 0u;
+      while (v_bx < 2u) {
+        v_tnz = (1u & (self->private_data.f_mb_states_top[a_mbx] >> (28u + v_bc + v_bx)));
+        self->private_data.f_mb_states_top[a_mbx] &= (4294967295u ^ (((uint32_t)(1u)) << (28u + v_bc + v_bx)));
+        v_lnz = wuffs_vp8__decoder__decode_block_coefficients(self,
+            a_workbuf,
+            a_mby,
+            a_seg,
+            ((2u * v_bc) +
+            (2u * v_by) +
+            v_bx +
+            16u),
+            2u,
+            (v_lnz + v_tnz));
+        self->private_data.f_mb_states_top[a_mbx] |= (v_lnz << (28u + v_bc + v_bx));
+        v_bx += 1u;
+      }
+      self->private_data.f_mb_states_left |= (v_lnz << (28u + v_bc + v_by));
+      v_by += 1u;
+    }
+    v_bc += 2u;
+  }
+  return wuffs_base__make_empty_struct();
+}
+
+// -------- func vp8.decoder.initialize_mb_coeffs
+
+WUFFS_BASE__GENERATED_C_CODE
+static wuffs_base__empty_struct
+wuffs_vp8__decoder__initialize_mb_coeffs(
+    wuffs_vp8__decoder* self) {
+  uint32_t v_i = 0;
+  uint32_t v_j = 0;
+
+  v_i = 0u;
+  while (v_i < 25u) {
+    v_j = 0u;
+    while (v_j < 16u) {
+      self->private_data.f_mb_coeffs[v_i][v_j] = 0u;
+      v_j += 1u;
+    }
+    v_i += 1u;
+  }
+  return wuffs_base__make_empty_struct();
+}
+
+// -------- func vp8.decoder.decode_block_coefficients
+
+WUFFS_BASE__GENERATED_C_CODE
+static uint32_t
+wuffs_vp8__decoder__decode_block_coefficients(
+    wuffs_vp8__decoder* self,
+    wuffs_base__slice_u8 a_workbuf,
+    uint32_t a_mby,
+    uint32_t a_seg,
+    uint32_t a_b,
+    uint32_t a_plane,
+    uint32_t a_context) {
+  uint32_t v_q1 = 0;
+  uint32_t v_q2 = 0;
+  uint32_t v_quant = 0;
+  uint32_t v_i = 0;
+  uint32_t v_part = 0;
+  uint32_t v_prob_base = 0;
+  uint32_t v_v1 = 0;
+  uint32_t v_value = 0;
+
+  v_q1 = 0u;
+  if (a_b == 24u) {
+    v_q1 = 1u;
+  } else if (a_b >= 16u) {
+    v_q1 = 2u;
+  }
+  v_i = 0u;
+  if (a_plane == 0u) {
+    v_i = 1u;
+  }
+  v_part = (1u + (a_mby & self->private_impl.f_num_other_partitions_m1));
+  v_prob_base = ((a_plane * 264u) + WUFFS_VP8__COEFF_BANDS_33[v_i] + (a_context * 11u));
+  v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, v_part, ((uint32_t)(self->private_data.f_coeff_probs[(v_prob_base + 0u)])));
+  if (v_v1 == 0u) {
+    return 0u;
+  }
+  while (true) {
+    v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, v_part, ((uint32_t)(self->private_data.f_coeff_probs[(v_prob_base + 1u)])));
+    if (v_v1 == 0u) {
+      v_i += 1u;
+      if (v_i >= 16u) {
+        break;
+      }
+      v_prob_base = ((a_plane * 264u) + WUFFS_VP8__COEFF_BANDS_33[(v_i + 0u)] + 0u);
+      continue;
+    }
+    v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, v_part, ((uint32_t)(self->private_data.f_coeff_probs[(v_prob_base + 2u)])));
+    if (v_v1 == 0u) {
+      v_value = 1u;
+      v_prob_base = ((a_plane * 264u) + WUFFS_VP8__COEFF_BANDS_33[(v_i + 1u)] + 11u);
+    } else {
+      v_value = wuffs_vp8__decoder__decode_large_value(self, a_workbuf, v_part, v_prob_base);
+      v_prob_base = ((a_plane * 264u) + WUFFS_VP8__COEFF_BANDS_33[(v_i + 1u)] + 22u);
+    }
+    v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, v_part, 128u);
+    if (v_v1 != 0u) {
+      v_value = ((uint32_t)(0u - v_value));
+    }
+    v_q2 = 0u;
+    if (v_i != 0u) {
+      v_q2 = 1u;
+    }
+    v_quant = ((uint32_t)(self->private_impl.f_dequants[a_seg][v_q1][v_q2]));
+    self->private_data.f_mb_coeffs[a_b][WUFFS_VP8__ZIGZAG[v_i]] = ((uint16_t)(((uint32_t)(v_value * v_quant))));
+    if (v_i >= 15u) {
+      break;
+    }
+    v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, v_part, ((uint32_t)(self->private_data.f_coeff_probs[(v_prob_base + 0u)])));
+    if (v_v1 == 0u) {
+      break;
+    }
+    v_i += 1u;
+  }
+  return 1u;
+}
+
+// -------- func vp8.decoder.decode_large_value
+
+WUFFS_BASE__GENERATED_C_CODE
+static uint32_t
+wuffs_vp8__decoder__decode_large_value(
+    wuffs_vp8__decoder* self,
+    wuffs_base__slice_u8 a_workbuf,
+    uint32_t a_part,
+    uint32_t a_prob_base) {
+  uint32_t v_v1 = 0;
+  uint32_t v_w1 = 0;
+  uint32_t v_category = 0;
+  uint32_t v_value = 0;
+  uint32_t v_i = 0;
+
+  v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, ((uint32_t)(self->private_data.f_coeff_probs[(a_prob_base + 3u)])));
+  if (v_v1 == 0u) {
+    v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, ((uint32_t)(self->private_data.f_coeff_probs[(a_prob_base + 4u)])));
+    if (v_v1 == 0u) {
+      return 2u;
+    }
+    v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, ((uint32_t)(self->private_data.f_coeff_probs[(a_prob_base + 5u)])));
+    return (3u + v_v1);
+  }
+  v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, ((uint32_t)(self->private_data.f_coeff_probs[(a_prob_base + 6u)])));
+  if (v_v1 == 0u) {
+    v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, ((uint32_t)(self->private_data.f_coeff_probs[(a_prob_base + 7u)])));
+    if (v_v1 == 0u) {
+      v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, 159u);
+      return (5u + v_v1);
+    }
+    v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, 165u);
+    v_w1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, 145u);
+    return (7u + (2u * v_v1) + v_w1);
+  }
+  v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, ((uint32_t)(self->private_data.f_coeff_probs[(a_prob_base + 8u)])));
+  v_w1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, ((uint32_t)(self->private_data.f_coeff_probs[(a_prob_base + 9u + v_v1)])));
+  v_category = ((2u * v_v1) + v_w1);
+  v_value = 0u;
+  v_i = 0u;
+  while (true) {
+    v_v1 = wuffs_vp8__decoder__read_bit(self, a_workbuf, a_part, ((uint32_t)(WUFFS_VP8__CATEGORY_PROBS[v_category][v_i])));
+    v_value <<= 1u;
+    v_value += v_v1;
+    v_i = ((v_i + 1u) & 15u);
+    if (WUFFS_VP8__CATEGORY_PROBS[v_category][v_i] == 0u) {
+      break;
+    }
+  }
+  return ((v_value & 2047u) + (((uint32_t)(8u)) << v_category) + 3u);
+}
+
 // -------- func vp8.decoder.get_quirk
 
 WUFFS_BASE__GENERATED_C_CODE
diff --git a/std/vp8/common_consts.wuffs b/std/vp8/common_consts.wuffs
index 648ec50..8787329 100644
--- a/std/vp8/common_consts.wuffs
+++ b/std/vp8/common_consts.wuffs
@@ -107,6 +107,10 @@
         254,
 ]
 
+pri const CLIP_9 : roarray[16] base.u8[..= 9] = [
+        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9,
+]
+
 // RFC 6386 Section 11.5. Subblock Mode Probability Table.
 //
 // Note that the specification (the RFC) differs from the implementation
@@ -243,6 +247,31 @@
         [112, 19, 12, 61, 195, 128, 48, 4, 24],
 ]]
 
+// RFC 6386 Section 13.2. Coding of Individual Coefficient Values.
+//
+// Categories 1 and 2 are inlined.
+pri const CATEGORY_PROBS : roarray[4] roarray[16] base.u8 = [[
+        // Category 3.
+        173, 148, 140, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+],[
+        // Category 4.
+        176, 155, 140, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+],[
+        // Category 5.
+        180, 157, 141, 134, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+],[
+        // Category 6.
+        254, 254, 243, 230, 196, 177, 153, 140, 133, 130, 129, 0, 0, 0, 0, 0,
+]]
+
+// RFC 6386 Section 13.3. Token Probabilities.
+//
+// These are the RFC's coeff_bands array values multplied by 33, with an extra
+// element at the end so we can index by (i+1).
+pri const COEFF_BANDS_33 : roarray[17] base.u32[..= 231] = [
+        0, 33, 66, 99, 198, 132, 165, 198, 198, 198, 198, 198, 198, 198, 198, 231, 0,
+]
+
 // RFC 6386 Section 13.4. Token Probability Updates.
 //
 // 1056 is (4 planes, 8 bands, 3 contexts, 11 tokens) flattened.
@@ -532,3 +561,29 @@
         244, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128,
         238, 1, 255, 128, 128, 128, 128, 128, 128, 128, 128,
 ]
+
+// RFC 6386 Section 14.1. Dequantization.
+pri const DEQUANTS : roarray[2] roarray[128] base.u16[..= 284] = [[
+        4, 5, 6, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 17,
+        18, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 28,
+        29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43,
+        44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
+        59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+        75, 76, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
+        91, 93, 95, 96, 98, 100, 101, 102, 104, 106, 108, 110, 112, 114, 116, 118,
+        122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 143, 145, 148, 151, 154, 157,
+],[
+        4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+        20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+        36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+        52, 53, 54, 55, 56, 57, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76,
+        78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108,
+        110, 112, 114, 116, 119, 122, 125, 128, 131, 134, 137, 140, 143, 146, 149, 152,
+        155, 158, 161, 164, 167, 170, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209,
+        213, 217, 221, 225, 229, 234, 239, 245, 249, 254, 259, 264, 269, 274, 279, 284,
+]]
+
+// RFC 6386 Section 20.16. tokens.c.
+pri const ZIGZAG : roarray[16] base.u8[..= 15] = [
+        0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15,
+]
diff --git a/std/vp8/decode_first_partition.wuffs b/std/vp8/decode_first_partition.wuffs
index ac6e0e6..2941788 100644
--- a/std/vp8/decode_first_partition.wuffs
+++ b/std/vp8/decode_first_partition.wuffs
@@ -74,6 +74,7 @@
     this.quant_y2ac_delta = this.read_signed!(workbuf: args.workbuf, part: 0, n: 4)
     this.quant_uvdc_delta = this.read_signed!(workbuf: args.workbuf, part: 0, n: 4)
     this.quant_uvac_delta = this.read_signed!(workbuf: args.workbuf, part: 0, n: 4)
+    this.calculate_dequants!()
 
     // RFC 6386 Section 9.7. Refresh Golden Frame and Altref Frame.
     if not this.is_key_frame {
@@ -203,6 +204,47 @@
     }
 }
 
+pri func decoder.calculate_dequants!() {
+    var seg : base.u32
+    var q   : base.u32
+
+    seg = 0
+    while seg < 4 {
+        q = this.quant_yac_qi
+        if not this.seg_enabled {
+            // No-op.
+        } else if this.seg_absolute {
+            q = this.util.sign_extend_convert_u8_u32(a: this.seg_quants[seg])
+        } else {
+            q ~mod+= this.util.sign_extend_convert_u8_u32(a: this.seg_quants[seg])
+        }
+
+        this.dequants[seg][0][0] = DEQUANTS[0][this.clip_127(a: q ~mod+ this.quant_ydc_delta)]
+        this.dequants[seg][0][1] = DEQUANTS[1][this.clip_127(a: q)]
+        this.dequants[seg][1][0] = DEQUANTS[0][this.clip_127(a: q ~mod+ this.quant_y2dc_delta)] * 2
+        this.dequants[seg][1][1] = (DEQUANTS[1][this.clip_127(a: q ~mod+ this.quant_y2ac_delta)] * 155) / 100
+        if this.dequants[seg][1][1] < 8 {
+            this.dequants[seg][1][1] = 8
+        }
+        this.dequants[seg][2][0] = DEQUANTS[0][this.clip_127(a: q ~mod+ this.quant_uvdc_delta)]
+        if this.dequants[seg][2][0] > 132 {
+            this.dequants[seg][2][0] = 132
+        }
+        this.dequants[seg][2][1] = DEQUANTS[1][this.clip_127(a: q ~mod+ this.quant_uvac_delta)]
+
+        seg += 1
+    }
+}
+
+pri func decoder.clip_127(a: base.u32) base.u32[..= 127] {
+    if args.a >= 0x8000_0000 {
+        return 0
+    } else if args.a >= 127 {
+        return 127
+    }
+    return args.a
+}
+
 pri func decoder.decode_other_partition_lengths!(workbuf: roslice base.u8) base.status {
     var v32       : base.u32
     var remainder : base.u32
diff --git a/std/vp8/decode_macroblocks.wuffs b/std/vp8/decode_macroblocks.wuffs
index 0fb2149..f56f454 100644
--- a/std/vp8/decode_macroblocks.wuffs
+++ b/std/vp8/decode_macroblocks.wuffs
@@ -16,10 +16,7 @@
     while mbx < this.mbw {
         assert mbx < 0x400 via "a < b: a < c; c <= b"(c: this.mbw)
 
-        this.mb_top_modes[mbx][0] = 0
-        this.mb_top_modes[mbx][1] = 0
-        this.mb_top_modes[mbx][2] = 0
-        this.mb_top_modes[mbx][3] = 0
+        this.mb_states_top[mbx] = 0
 
         mbx += 1
     }
@@ -28,10 +25,7 @@
     while mby < this.mbh {
         assert mby < 0x400 via "a < b: a < c; c <= b"(c: this.mbh)
 
-        this.mb_left_modes[0] = 0
-        this.mb_left_modes[1] = 0
-        this.mb_left_modes[2] = 0
-        this.mb_left_modes[3] = 0
+        this.mb_states_left = 0
 
         mbx = 0
         while mbx < this.mbw,
@@ -81,8 +75,14 @@
     chroma_mode = this.decode_chroma_mode!(workbuf: args.workbuf)
 
     if skip {
-        // TODO.
+        // Clear the HNZC bits.
+        this.mb_states_left &= 0x0000_FFFF
+        this.mb_states_top[args.mbx] &= 0x0000_FFFF
+
     } else {
+        this.decode_residuals!(
+                workbuf: args.workbuf, mbx: args.mbx, mby: args.mby,
+                seg: seg, luma_mode: luma_mode, chroma_mode: chroma_mode)
     }
 }
 
@@ -94,6 +94,11 @@
 // 3 = B_HE_PRED = predict columns using column to the left.
 // 4 = B_PRED    = each Y subblock is independently predicted.
 //
+// Returning (as luma_mode) at least 4 (equivalently, returning B_PRED) means
+// that we use "intra4x4 prediction" (as opposed to "intra16x16 prediction").
+// (luma_mode >= 4) here is equivalent to libwebp's "is_i4x4 == true" and
+// golang.org/x/image/vp8's "usePredY16 == false".
+//
 // The RFC gives an enum in (DC_PRED, V_PRED, H_PRED, TM_PRED, B_PRED) order
 // but the libwebp implementation uses a different one, (B_DC_PRED, B_TM_PRED,
 // B_VE_PRED, B_HE_PRED, B_PRED). Modulo the B_ prefixes, it's DC,V,H,TM versus
@@ -106,9 +111,11 @@
 
     v1 = this.read_bit!(workbuf: args.workbuf, part: 0, prob: 145)
     if v1 == 0 {
-        return 4  // 4=B_PRED.
+        return 4  // 4=B_PRED. is_i4x4 == true. usePredY16 == false.
     }
 
+    // Otherwise, is_i4x4 == false. usePredY16 == true.
+
     v1 = this.read_bit!(workbuf: args.workbuf, part: 0, prob: 156)
     if v1 == 0 {
         v1 = this.read_bit!(workbuf: args.workbuf, part: 0, prob: 163)
@@ -144,33 +151,27 @@
         workbuf: slice base.u8,
         mbx: base.u32[..= 0x3FF],
         luma_mode: base.u32[..= 4]) {
-    var i          : base.u32
-    var top_mode : base.u8[..= 9]
-    var left_mode  : base.u8[..= 9]
-    var mode       : base.u8[..= 9]
+    var i         : base.u32
+    var top_mode  : base.u8[..= 9]
+    var left_mode : base.u8[..= 9]
+    var mode      : base.u8[..= 9]
 
     if args.luma_mode < 4 {
-        this.mb_top_modes[args.mbx][0] = mode
-        this.mb_top_modes[args.mbx][1] = mode
-        this.mb_top_modes[args.mbx][2] = mode
-        this.mb_top_modes[args.mbx][3] = mode
-        this.mb_left_modes[0] = mode
-        this.mb_left_modes[1] = mode
-        this.mb_left_modes[2] = mode
-        this.mb_left_modes[3] = mode
+        this.mb_states_top[args.mbx] = (mode as base.u32) * 0x1111
+        this.mb_states_left = (mode as base.u32) * 0x1111
         return nothing
     }
 
     i = 0
     while i < 16 {
         if i < 4 {
-            top_mode = this.mb_top_modes[args.mbx][i]
+            top_mode = CLIP_9[15 & (this.mb_states_top[args.mbx] >> (i * 4))]
         } else {
             top_mode = this.mb_subblock_modes[i - 4]
         }
 
         if (i & 3) == 0 {
-            left_mode = this.mb_left_modes[i >> 2]
+            left_mode = CLIP_9[15 & (this.mb_states_left >> (i & 12))]
         } else {
             left_mode = this.mb_subblock_modes[(i ~mod+ 15) & 15]
         }
@@ -181,14 +182,16 @@
         i += 1
     }
 
-    this.mb_top_modes[args.mbx][0] = this.mb_subblock_modes[0xC]
-    this.mb_top_modes[args.mbx][1] = this.mb_subblock_modes[0xD]
-    this.mb_top_modes[args.mbx][2] = this.mb_subblock_modes[0xE]
-    this.mb_top_modes[args.mbx][3] = this.mb_subblock_modes[0xF]
-    this.mb_left_modes[0] = this.mb_subblock_modes[0x3]
-    this.mb_left_modes[1] = this.mb_subblock_modes[0x7]
-    this.mb_left_modes[2] = this.mb_subblock_modes[0xB]
-    this.mb_left_modes[3] = this.mb_subblock_modes[0xF]
+    this.mb_states_top[args.mbx] = (this.mb_states_top[args.mbx] & 0xFFFF_0000) |
+            ((this.mb_subblock_modes[0xC] as base.u32) << 0x0) |
+            ((this.mb_subblock_modes[0xD] as base.u32) << 0x4) |
+            ((this.mb_subblock_modes[0xE] as base.u32) << 0x8) |
+            ((this.mb_subblock_modes[0xF] as base.u32) << 0xC)
+    this.mb_states_left = (this.mb_states_left & 0xFFFF_0000) |
+            ((this.mb_subblock_modes[0x3] as base.u32) << 0x0) |
+            ((this.mb_subblock_modes[0x7] as base.u32) << 0x4) |
+            ((this.mb_subblock_modes[0xB] as base.u32) << 0x8) |
+            ((this.mb_subblock_modes[0xF] as base.u32) << 0xC)
 }
 
 // RFC 6386 Section 11.3. Subblock Mode Contexts.
diff --git a/std/vp8/decode_residuals.wuffs b/std/vp8/decode_residuals.wuffs
new file mode 100644
index 0000000..6060b5a
--- /dev/null
+++ b/std/vp8/decode_residuals.wuffs
@@ -0,0 +1,292 @@
+// Copyright 2026 The Wuffs Authors.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+pri func decoder.decode_residuals!(
+        workbuf: slice base.u8,
+        mbx: base.u32[..= 0x3FF],
+        mby: base.u32[..= 0x3FF],
+        seg: base.u32[..= 3],
+        luma_mode: base.u32[..= 4],
+        chroma_mode: base.u32[..= 3]) {
+    var bc    : base.u32
+    var by    : base.u32
+    var bx    : base.u32
+    var plane : base.u32[..= 3]
+    var lnz   : base.u32[..= 1]
+    var tnz   : base.u32[..= 1]
+
+    this.initialize_mb_coeffs!()
+
+    // Handle "intra16x16 prediction".
+    plane = 3  // Plane 3: Y beginning at coefficient 0.
+    if args.luma_mode < 4 {
+        lnz = 1 & (this.mb_states_left >> 23)
+        this.mb_states_left &= 0xFF7F_FFFF
+
+        tnz = 1 & (this.mb_states_top[args.mbx] >> 23)
+        this.mb_states_top[args.mbx] &= 0xFF7F_FFFF
+
+        lnz = this.decode_block_coefficients!(
+                workbuf: args.workbuf,
+                mby: args.mby,
+                seg: args.seg,
+                b: 24,
+                plane: 1,  // Plane 1: Y2.
+                context: lnz + tnz)
+
+        this.mb_states_top[args.mbx] |= lnz << 23
+        this.mb_states_left |= lnz << 23
+        plane = 0  // Plane 0: Y beginning at coefficient 1.
+    }
+
+    // Parse Luma coefficients.
+
+    by = 0
+    while by < 4 {
+        lnz = 1 & (this.mb_states_left >> (24 + by))
+        this.mb_states_left &= 0xFFFF_FFFF ^ ((1 as base.u32) << (24 + by))
+
+        bx = 0
+        while bx < 4,
+                inv by < 4,
+        {
+            tnz = 1 & (this.mb_states_top[args.mbx] >> (24 + bx))
+            this.mb_states_top[args.mbx] &= 0xFFFF_FFFF ^ ((1 as base.u32) << (24 + bx))
+
+            lnz = this.decode_block_coefficients!(
+                    workbuf: args.workbuf,
+                    mby: args.mby,
+                    seg: args.seg,
+                    b: (4 * by) + bx,
+                    plane: plane,
+                    context: lnz + tnz)
+
+            this.mb_states_top[args.mbx] |= lnz << (24 + bx)
+            bx += 1
+        }
+        this.mb_states_left |= lnz << (24 + by)
+        by += 1
+    }
+
+    // Parse Chroma coefficients.
+
+    bc = 0
+    while bc <= 2 {
+        by = 0
+        while by < 2,
+                inv bc <= 2,
+        {
+            lnz = 1 & (this.mb_states_left >> (28 + bc + by))
+            this.mb_states_left &= 0xFFFF_FFFF ^ ((1 as base.u32) << (28 + bc + by))
+
+            bx = 0
+            while bx < 2,
+                    inv bc <= 2,
+                    inv by < 2,
+            {
+                tnz = 1 & (this.mb_states_top[args.mbx] >> (28 + bc + bx))
+                this.mb_states_top[args.mbx] &= 0xFFFF_FFFF ^ ((1 as base.u32) << (28 + bc + bx))
+
+                lnz = this.decode_block_coefficients!(
+                        workbuf: args.workbuf,
+                        mby: args.mby,
+                        seg: args.seg,
+                        b: (2 * bc) + (2 * by) + bx + 16,
+                        plane: 2,  // Plane 2: U or V.
+                        context: lnz + tnz)
+
+                this.mb_states_top[args.mbx] |= lnz << (28 + bc + bx)
+                bx += 1
+            }
+            this.mb_states_left |= lnz << (28 + bc + by)
+            by += 1
+        }
+        bc += 2
+    }
+}
+
+pri func decoder.initialize_mb_coeffs!() {
+    var i : base.u32
+    var j : base.u32
+
+    i = 0
+    while i < 25 {
+        j = 0
+        while j < 16,
+                inv i < 25,
+        {
+            this.mb_coeffs[i][j] = 0
+            j += 1
+        }
+        i += 1
+    }
+}
+
+pri func decoder.decode_block_coefficients!(
+        workbuf: slice base.u8,
+        mby: base.u32[..= 0x3FF],
+        seg: base.u32[..= 3],
+        b: base.u32[..= 24],
+        plane: base.u32[..= 3],
+        context: base.u32[..= 2]) base.u32[..= 1] {
+    var q1        : base.u32[..= 2]
+    var q2        : base.u32[..= 1]
+    var quant     : base.u32
+    var i         : base.u32
+    var part      : base.u32[..= 8]
+    var prob_base : base.u32[..= 1045]
+    var v1        : base.u32[..= 1]
+    var value     : base.u32
+
+    q1 = 0
+    if args.b == 24 {
+        q1 = 1
+    } else if args.b >= 16 {
+        q1 = 2
+    }
+
+    i = 0
+    assert i <= 1
+    if args.plane == 0 {
+        i = 1
+        assert i <= 1
+    }
+
+    part = 1 + (args.mby & this.num_other_partitions_m1)
+    prob_base = (args.plane * (8 * 3 * 11)) + COEFF_BANDS_33[i] + (args.context * 11)
+
+    v1 = this.read_bit!(workbuf: args.workbuf, part: part,
+            prob: this.coeff_probs[prob_base + 0] as base.u32)
+    if v1 == 0 {
+        return 0
+    }
+
+    while true,
+            pre i < 16,
+    {
+        v1 = this.read_bit!(workbuf: args.workbuf, part: part,
+                prob: this.coeff_probs[prob_base + 1] as base.u32)
+        if v1 == 0 {
+            i += 1
+            if i >= 16 {
+                break
+            }
+            prob_base = (args.plane * (8 * 3 * 11)) + COEFF_BANDS_33[i + 0] + (0 * 11)
+            continue
+        }
+
+        v1 = this.read_bit!(workbuf: args.workbuf, part: part,
+                prob: this.coeff_probs[prob_base + 2] as base.u32)
+        if v1 == 0 {
+            value = 1
+            prob_base = (args.plane * (8 * 3 * 11)) + COEFF_BANDS_33[i + 1] + (1 * 11)
+        } else {
+            value = this.decode_large_value!(
+                    workbuf: args.workbuf,
+                    part: part,
+                    prob_base: prob_base)
+            prob_base = (args.plane * (8 * 3 * 11)) + COEFF_BANDS_33[i + 1] + (2 * 11)
+        }
+
+        v1 = this.read_bit!(workbuf: args.workbuf, part: part, prob: 128)
+        if v1 <> 0 {
+            value = 0 ~mod- value
+        }
+
+        q2 = 0
+        if i <> 0 {
+            q2 = 1
+        }
+        quant = this.dequants[args.seg][q1][q2] as base.u32
+        this.mb_coeffs[args.b][ZIGZAG[i]] = ((value ~mod* quant) & 0xFFFF) as base.u16
+
+        if i >= 15 {
+            break
+        }
+
+        v1 = this.read_bit!(workbuf: args.workbuf, part: part,
+                prob: this.coeff_probs[prob_base + 0] as base.u32)
+        if v1 == 0 {
+            break
+        }
+
+        i += 1
+    }
+
+    return 1
+}
+
+pri func decoder.decode_large_value!(
+        workbuf: slice base.u8,
+        part: base.u32[..= 8],
+        prob_base: base.u32[..= 1045]) base.u32[2 ..= 2114] {
+    var v1       : base.u32[..= 1]
+    var w1       : base.u32[..= 1]
+    var category : base.u32[..= 3]
+    var value    : base.u32
+    var i        : base.u32[..= 15]
+
+    v1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+            prob: this.coeff_probs[args.prob_base + 3] as base.u32)
+    if v1 == 0 {
+        v1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+                prob: this.coeff_probs[args.prob_base + 4] as base.u32)
+        if v1 == 0 {
+            return 2
+        }
+
+        v1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+                prob: this.coeff_probs[args.prob_base + 5] as base.u32)
+        return 3 + v1
+    }
+
+    v1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+            prob: this.coeff_probs[args.prob_base + 6] as base.u32)
+    if v1 == 0 {
+        v1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+                prob: this.coeff_probs[args.prob_base + 7] as base.u32)
+        if v1 == 0 {
+            // Category 1.
+            v1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+                    prob: 159)
+            return 5 + v1
+        }
+
+        // Category 2.
+        v1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+                prob: 165)
+        w1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+                prob: 145)
+        return 7 + (2 * v1) + w1
+    }
+
+    // Categories 3, 4, 5, 6.
+    v1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+            prob: this.coeff_probs[args.prob_base + 8] as base.u32)
+    w1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+            prob: this.coeff_probs[args.prob_base + 9 + v1] as base.u32)
+    category = (2 * v1) + w1
+
+    // Read 3, 4, 5 or 11 extra bits, depending on the category.
+    value = 0
+    i = 0
+    while true {
+        v1 = this.read_bit!(workbuf: args.workbuf, part: args.part,
+                prob: CATEGORY_PROBS[category][i] as base.u32)
+        value ~mod<<= 1
+        value ~mod+= v1
+
+        i = (i + 1) & 15
+        if CATEGORY_PROBS[category][i] == 0 {
+            break
+        }
+    }
+    return (value & 0x7FF) + ((8 as base.u32) << category) + 3
+}
diff --git a/std/vp8/decode_vp8.wuffs b/std/vp8/decode_vp8.wuffs
index fafc64f..67a247e 100644
--- a/std/vp8/decode_vp8.wuffs
+++ b/std/vp8/decode_vp8.wuffs
@@ -88,13 +88,17 @@
         quant_uvdc_delta : base.u32,
         quant_uvac_delta : base.u32,
 
+        // Look-up tables derived from the dequantization parameters.
+        //
+        // The first index is the segment. The second index is Y/Y2/UV. The
+        // third index is DC/AC.
+        dequants : array[4] array[3] array[2] base.u16,
+
         // These 9 bits combine what RFC 6386 calls mb_no_skip_coeff (which we
         // hold in the 0x100 bit) and prob_skip_false (in the low 8 bits).
         prob_skip : base.u32[..= 0x1FF],
 
         mb_subblock_modes : array[16] base.u8[..= 9],
-        mb_left_modes     : array[4] base.u8[..= 9],
-        mb_top_modes      : array[0x400] array[4] base.u8[..= 9],
 
         dst_x : base.u32,
         dst_y : base.u32,
@@ -104,6 +108,25 @@
 ) + (
         // 1056 is (4 planes, 8 bands, 3 contexts, 11 tokens) flattened.
         coeff_probs : array[1056] base.u8,
+
+        mb_coeffs : array[25] array[16] base.u16,
+
+        // Macroblock states are a u32 whose bits are packed like this:
+        //
+        //  - 28 ..= 31 are Chroma (UV)  HNZC bits.
+        //  - 24 ..= 27 are Luma4  (Y4)  HNZC bits.
+        //  - 23        is  Luma16 (Y16) HNZC bit.
+        //  - 16 ..= 22 are unused.
+        //  - 12 ..= 15 are the 3rd predictor mode.
+        //  -  8 ..= 12 are the 2nd predictor mode.
+        //  -  4 ..=  7 are the 1st predictor mode.
+        //  -  0 ..=  3 are the 0th predictor mode.
+        //
+        // HNZC stands for has-non-zero-coefficients.
+        //
+        // The mb_states_top array is indexed by mbx.
+        mb_states_left : base.u32,
+        mb_states_top  : array[0x400] base.u32,
 )
 
 pub func decoder.get_quirk(key: base.u32) base.u64 {