diff --git a/bin/crunch_x64.exe b/bin/crunch_x64.exe index 95e58a6..3a1d02b 100644 Binary files a/bin/crunch_x64.exe and b/bin/crunch_x64.exe differ diff --git a/crnlib/crn_comp.cpp b/crnlib/crn_comp.cpp index f305ec1..0f73d67 100644 --- a/crnlib/crn_comp.cpp +++ b/crnlib/crn_comp.cpp @@ -635,15 +635,19 @@ bool crn_comp::pack_selectors( } bool crn_comp::pack_chunks( - uint first_chunk, uint num_chunks, + uint group, bool clear_histograms, symbol_codec* pCodec, const crnlib::vector* pColor_endpoint_remap, const crnlib::vector* pColor_selector_remap, const crnlib::vector* pAlpha_endpoint_remap, const crnlib::vector* pAlpha_selector_remap) { + uint first_chunk = m_mip_groups[group].m_first_chunk; + uint num_chunks = m_mip_groups[group].m_num_chunks; + uint chunk_width = m_mip_groups[group].m_chunk_width; + if (!pCodec) { - m_chunk_encoding_hist.resize(1 << (3 * cEncodingMapNumChunksPerCode)); + m_chunk_encoding_hist.resize(256); if (clear_histograms) m_chunk_encoding_hist.set_all(0); @@ -676,137 +680,60 @@ bool crn_comp::pack_chunks( } } - uint endpoint_index[cNumComps][2][2] = {}; - uint selector_index[cNumComps][2][2] = {}; - - uint num_encodings_left = 0; - - for (uint chunk_index = first_chunk; chunk_index < (first_chunk + num_chunks); chunk_index++) { - if (!num_encodings_left) { - uint index = 0; - for (uint i = 0; i < cEncodingMapNumChunksPerCode; i++) - if ((chunk_index + i) < (first_chunk + num_chunks)) - index |= (m_hvq.get_chunk_encoding(chunk_index + i).m_encoding_index << (i * 3)); - - if (pCodec) - pCodec->encode(index, m_chunk_encoding_dm); - else - m_chunk_encoding_hist.inc_freq(index); - - num_encodings_left = cEncodingMapNumChunksPerCode; + uint selector_index[cNumComps] = {}; + uint endpoint_index[cNumComps] = {}; + const crnlib::vector* endpoint_remap[cNumComps] = {}; + const crnlib::vector* selector_remap[cNumComps] = {}; + for (uint c = 0; c < cNumComps; c++) { + if (m_has_comp[c]) { + endpoint_remap[c] = c ? pAlpha_endpoint_remap : pColor_endpoint_remap; + selector_remap[c] = c ? pAlpha_selector_remap : pColor_selector_remap; } - num_encodings_left--; + } - const dxt_hc::chunk_encoding& encoding = m_hvq.get_chunk_encoding(chunk_index); - const chunk_detail& details = m_chunk_details[chunk_index]; - - const uint comp_order[3] = {cAlpha0, cAlpha1, cColor}; - for (uint c = 0; c < 3; c++) { - const uint comp_index = comp_order[c]; - if (!m_has_comp[comp_index]) - continue; - - // endpoints - if (comp_index == cColor) { - if (pColor_endpoint_remap) { - for (uint y = 0; y < 2; y++) { - for (uint x = 0; x < 2; x++) { - uint8 endpoint_reference = details.m_endpoint_references[comp_index][y][x]; - if (!endpoint_reference) { - endpoint_index[comp_index][y][x] = (*pColor_endpoint_remap)[details.m_endpoint_indices[comp_index][y][x]]; - int endpoint_delta = endpoint_index[comp_index][y][x] - endpoint_index[comp_index][y][x ^ 1]; - - int sym = endpoint_delta; + for (uint chunk_base = first_chunk; chunk_base < first_chunk + num_chunks; chunk_base += chunk_width) { + for (uint by = 0; by < 2; by++) { + for (uint cx = 0; cx < chunk_width; cx++) { + const chunk_detail& details = m_chunk_details[chunk_base + cx]; + if (!by) { + if (pCodec) + pCodec->encode(details.m_reference_group, m_reference_encoding_dm); + else + m_chunk_encoding_hist.inc_freq(details.m_reference_group); + } + for (uint bx = 0; bx < 2; bx++) { + for (uint c = 0; c < cNumComps; c++) { + if (endpoint_remap[c]) { + uint index = (*endpoint_remap[c])[details.m_endpoint_indices[by][bx][c]]; + if (!details.m_endpoint_references[by][bx]) { + int sym = index - endpoint_index[c]; if (sym < 0) - sym += pColor_endpoint_remap->size(); - - CRNLIB_ASSERT(sym >= 0 && sym < (int)pColor_endpoint_remap->size()); - + sym += endpoint_remap[c]->size(); if (!pCodec) - m_endpoint_index_hist[0].inc_freq(sym); + m_endpoint_index_hist[c ? 1 : 0].inc_freq(sym); else - pCodec->encode(sym, m_endpoint_index_dm[0]); - } else { - endpoint_index[comp_index][y][x] = endpoint_reference == 1 ? endpoint_index[comp_index][y][x ^ 1] : endpoint_index[comp_index][y ^ 1][x]; + pCodec->encode(sym, m_endpoint_index_dm[c ? 1 : 0]); } + endpoint_index[c] = index; } } - } - } else { - if (pAlpha_endpoint_remap) { - for (uint y = 0; y < 2; y++) { - for (uint x = 0; x < 2; x++) { - uint8 endpoint_reference = details.m_endpoint_references[comp_index][y][x]; - if (!endpoint_reference) { - endpoint_index[comp_index][y][x] = (*pAlpha_endpoint_remap)[details.m_endpoint_indices[comp_index][y][x]]; - int endpoint_delta = endpoint_index[comp_index][y][x] - endpoint_index[comp_index][y][x ^ 1]; - - int sym = endpoint_delta; - if (sym < 0) - sym += pAlpha_endpoint_remap->size(); - - CRNLIB_ASSERT(sym >= 0 && sym < (int)pAlpha_endpoint_remap->size()); - - if (!pCodec) - m_endpoint_index_hist[1].inc_freq(sym); - else - pCodec->encode(sym, m_endpoint_index_dm[1]); - } else { - endpoint_index[comp_index][y][x] = endpoint_reference == 1 ? endpoint_index[comp_index][y][x ^ 1] : endpoint_index[comp_index][y ^ 1][x]; - } + for (uint c = 0; c < cNumComps; c++) { + if (selector_remap[c]) { + uint index = (*selector_remap[c])[details.m_selector_indices[by][bx][c]]; + int sym = index - selector_index[c]; + if (sym < 0) + sym += selector_remap[c]->size(); + if (!pCodec) + m_selector_index_hist[c ? 1 : 0].inc_freq(sym); + else + pCodec->encode(sym, m_selector_index_dm[c ? 1 : 0]); + selector_index[c] = index; } } } } - } // c - - // selectors - for (uint y = 0; y < 2; y++) { - for (uint x = 0; x < 2; x++) { - for (uint c = 0; c < 3; c++) { - const uint comp_index = comp_order[c]; - if (!m_has_comp[comp_index]) - continue; - - if (comp_index == cColor) { - if (pColor_selector_remap) { - selector_index[comp_index][y][x] = (*pColor_selector_remap)[details.m_selector_indices[comp_index][y][x]]; - int selector_delta = selector_index[comp_index][y][x] - selector_index[comp_index][y][x ^ 1]; - - int sym = selector_delta; - if (sym < 0) - sym += pColor_selector_remap->size(); - - CRNLIB_ASSERT(sym >= 0 && sym < (int)pColor_selector_remap->size()); - - if (!pCodec) - m_selector_index_hist[cColor].inc_freq(sym); - else - pCodec->encode(sym, m_selector_index_dm[cColor]); - } - } else if (pAlpha_selector_remap) { - selector_index[comp_index][y][x] = (*pAlpha_selector_remap)[details.m_selector_indices[comp_index][y][x]]; - int selector_delta = selector_index[comp_index][y][x] - selector_index[comp_index][y][x ^ 1]; - - int sym = selector_delta; - if (sym < 0) - sym += pAlpha_selector_remap->size(); - - CRNLIB_ASSERT(sym >= 0 && sym < (int)pAlpha_selector_remap->size()); - - if (!pCodec) - m_selector_index_hist[1].inc_freq(sym); - else - pCodec->encode(sym, m_selector_index_dm[1]); - } - - } // c - - } // x - } // y - - } // chunk_index - + } + } return true; } @@ -817,14 +744,16 @@ bool crn_comp::pack_chunks_simulation( const crnlib::vector* pColor_selector_remap, const crnlib::vector* pAlpha_endpoint_remap, const crnlib::vector* pAlpha_selector_remap) { - if (!pack_chunks(first_chunk, num_chunks, true, NULL, pColor_endpoint_remap, pColor_selector_remap, pAlpha_endpoint_remap, pAlpha_selector_remap)) - return false; + for (uint group = 0; group < m_mip_groups.size(); group++) { + if (!pack_chunks(group, !group, NULL, pColor_endpoint_remap, pColor_selector_remap, pAlpha_endpoint_remap, pAlpha_selector_remap)) + return false; + } symbol_codec codec; codec.start_encoding(2 * 1024 * 1024); codec.encode_enable_simulation(true); - m_chunk_encoding_dm.init(true, m_chunk_encoding_hist, 16); + m_reference_encoding_dm.init(true, m_chunk_encoding_hist, 16); for (uint i = 0; i < 2; i++) { if (m_endpoint_index_hist[i].size()) { @@ -840,8 +769,10 @@ bool crn_comp::pack_chunks_simulation( } } - if (!pack_chunks(first_chunk, num_chunks, false, &codec, pColor_endpoint_remap, pColor_selector_remap, pAlpha_endpoint_remap, pAlpha_selector_remap)) - return false; + for (uint group = 0; group < m_mip_groups.size(); group++) { + if (!pack_chunks(group, false, &codec, pColor_endpoint_remap, pColor_selector_remap, pAlpha_endpoint_remap, pAlpha_selector_remap)) + return false; + } codec.stop_encoding(false); @@ -941,6 +872,7 @@ bool crn_comp::alias_images() { mip_group_chunk_index = 0; m_mip_groups[mip_group].m_num_chunks += num_chunks; + m_mip_groups[mip_group].m_chunk_width = chunk_width; m_levels[level_index].m_width = width; m_levels[level_index].m_height = height; @@ -1031,7 +963,7 @@ void crn_comp::clear() { m_hvq.clear(); m_chunk_encoding_hist.clear(); - m_chunk_encoding_dm.clear(); + m_reference_encoding_dm.clear(); for (uint i = 0; i < 2; i++) { m_endpoint_index_hist[i].clear(); m_endpoint_index_dm[i].clear(); @@ -1209,30 +1141,34 @@ void crn_comp::create_chunk_indices() { { 0, 1, 2, 3 }, }; - uint8 endpoint_references[8][4] = { - { 0, 1, 2, 1 }, - { 0, 1, 0, 1 }, - { 0, 0, 2, 2 }, - { 0, 1, 0, 0 }, - { 0, 0, 0, 1 }, - { 0, 0, 2, 0 }, - { 0, 0, 0, 2 }, - { 0, 0, 0, 0 }, - }; - m_chunk_details.resize(m_total_chunks); - for (uint chunk_index = 0; chunk_index < m_total_chunks; chunk_index++) { - const dxt_hc::chunk_encoding& chunk_encoding = m_hvq.get_chunk_encoding(chunk_index); - - for (uint i = 0; i < cNumComps; i++) { - if (!m_has_comp[i]) - continue; - for (uint t = 0, y = 0; y < cChunkBlockHeight; y++) { - for (uint x = 0; x < cChunkBlockWidth; x++, t++) { - m_chunk_details[chunk_index].m_selector_indices[i][y][x] = chunk_encoding.m_selector_indices[i][y][x]; - m_chunk_details[chunk_index].m_endpoint_indices[i][y][x] = chunk_encoding.m_endpoint_indices[i][endpoint_index_map[chunk_encoding.m_encoding_index][t]]; - m_chunk_details[chunk_index].m_endpoint_references[i][y][x] = endpoint_references[chunk_encoding.m_encoding_index][t]; + for (uint group = 0; group < m_mip_groups.size(); group++) { + uint chunk_width = m_mip_groups[group].m_chunk_width; + for (uint i = 0; i < m_mip_groups[group].m_num_chunks;) { + for (uint cx = 0; cx < chunk_width; cx++, i++) { + uint chunk_index = m_mip_groups[group].m_first_chunk + i, left_chunk_index = 0, top_chunk_index = 0; + const dxt_hc::chunk_encoding& chunk_encoding = m_hvq.get_chunk_encoding(chunk_index); + for (uint t = 0, by = 0; by < 2; by++) { + for (uint bx = 0; bx < 2; bx++, t++) { + bool left_match = bx || cx; + if (left_match) + left_chunk_index = bx ? chunk_index : chunk_index - 1; + bool top_match = by || i >= chunk_width; + if (top_match) + top_chunk_index = by ? chunk_index : chunk_index - chunk_width; + for (uint c = 0; c < cNumComps; c++) { + if (m_has_comp[c]) { + m_chunk_details[chunk_index].m_endpoint_indices[by][bx][c] = chunk_encoding.m_endpoint_indices[c][endpoint_index_map[chunk_encoding.m_encoding_index][t]]; + left_match = left_match && m_chunk_details[chunk_index].m_endpoint_indices[by][bx][c] == m_chunk_details[left_chunk_index].m_endpoint_indices[by][bx ^ 1][c]; + top_match = top_match && m_chunk_details[chunk_index].m_endpoint_indices[by][bx][c] == m_chunk_details[top_chunk_index].m_endpoint_indices[by ^ 1][bx][c]; + m_chunk_details[chunk_index].m_selector_indices[by][bx][c] = chunk_encoding.m_selector_indices[c][by][bx]; + } + } + uint8 endpoint_reference = left_match ? 1 : top_match ? 2 : 0; + m_chunk_details[chunk_index].m_endpoint_references[by][bx] = endpoint_reference; + m_chunk_details[chunk_index].m_reference_group |= endpoint_reference << (bx << 2 | by << 1); + } } } } @@ -1297,13 +1233,10 @@ bool crn_comp::optimize_color_endpoint_codebook(crnlib::vector& remapping) const chunk_detail& details = m_chunk_details[chunk_index]; for (uint y = 0; y < 2; y++) { for (uint x = 0; x < 2; x++) { - uint8 endpoint_reference = details.m_endpoint_references[cColor][y][x]; - if (!endpoint_reference) { - endpoint_index[y][x] = details.m_endpoint_indices[cColor][y][x]; + endpoint_index[y][x] = details.m_endpoint_indices[y][x][cColor]; + if (!details.m_endpoint_references[y][x]) { update_hist(xhist, endpoint_index[y][x], endpoint_index[y][x ^ 1], n); update_hist(xhist, endpoint_index[y][x ^ 1], endpoint_index[y][x], n); - } else { - endpoint_index[y][x] = endpoint_reference == 1 ? endpoint_index[y][x ^ 1] : endpoint_index[y ^ 1][x]; } } } @@ -1425,7 +1358,7 @@ bool crn_comp::optimize_color_selector_codebook(crnlib::vector& remapping) const chunk_detail& details = m_chunk_details[chunk_index]; for (uint y = 0; y < 2; y++) { for (uint x = 0; x < 2; x++) { - selector_index[y][x] = details.m_selector_indices[cColor][y][x]; + selector_index[y][x] = details.m_selector_indices[y][x][cColor]; update_hist(xhist, selector_index[y][x], selector_index[y][x ^ 1], n); update_hist(xhist, selector_index[y][x ^ 1], selector_index[y][x], n); } @@ -1542,20 +1475,17 @@ bool crn_comp::optimize_alpha_endpoint_codebook(crnlib::vector& remapping) uint n = m_hvq.get_alpha_endpoint_codebook_size(); hist_type xhist(n * n); - uint endpoint_index[cNumComps][2][2] = {}; + uint endpoint_index[2][2][cNumComps] = {}; uint min_comp_index = m_has_comp[cAlpha0] ? cAlpha0 : cAlpha1, max_comp_index = m_has_comp[cAlpha1] ? cAlpha1 : cAlpha0; for (uint chunk_index = 0; chunk_index < m_chunks.size(); chunk_index++) { const chunk_detail& details = m_chunk_details[chunk_index]; - for (uint comp_index = min_comp_index; comp_index <= max_comp_index; comp_index++) { - for (uint y = 0; y < 2; y++) { - for (uint x = 0; x < 2; x++) { - uint8 endpoint_reference = details.m_endpoint_references[comp_index][y][x]; - if (!endpoint_reference) { - endpoint_index[comp_index][y][x] = details.m_endpoint_indices[comp_index][y][x]; - update_hist(xhist, endpoint_index[comp_index][y][x], endpoint_index[comp_index][y][x ^ 1], n); - update_hist(xhist, endpoint_index[comp_index][y][x ^ 1], endpoint_index[comp_index][y][x], n); - } else { - endpoint_index[comp_index][y][x] = endpoint_reference == 1 ? endpoint_index[comp_index][y][x ^ 1] : endpoint_index[comp_index][y ^ 1][x]; + for (uint y = 0; y < 2; y++) { + for (uint x = 0; x < 2; x++) { + for (uint comp_index = min_comp_index; comp_index <= max_comp_index; comp_index++) { + endpoint_index[y][x][comp_index] = details.m_endpoint_indices[y][x][comp_index]; + if (!details.m_endpoint_references[y][x]) { + update_hist(xhist, endpoint_index[y][x][comp_index], endpoint_index[y][x ^ 1][comp_index], n); + update_hist(xhist, endpoint_index[y][x ^ 1][comp_index], endpoint_index[y][x][comp_index], n); } } } @@ -1678,7 +1608,7 @@ bool crn_comp::optimize_alpha_selector_codebook(crnlib::vector& remapping) for (uint comp_index = min_comp_index; comp_index <= max_comp_index; comp_index++) { for (uint y = 0; y < 2; y++) { for (uint x = 0; x < 2; x++) { - selector_index[comp_index][y][x] = details.m_selector_indices[comp_index][y][x]; + selector_index[comp_index][y][x] = details.m_selector_indices[y][x][comp_index]; update_hist(xhist, selector_index[comp_index][y][x], selector_index[comp_index][y][x ^ 1], n); update_hist(xhist, selector_index[comp_index][y][x ^ 1], selector_index[comp_index][y][x], n); } @@ -1749,7 +1679,7 @@ bool crn_comp::pack_data_models() { symbol_codec codec; codec.start_encoding(1024 * 1024); - if (!codec.encode_transmit_static_huffman_data_model(m_chunk_encoding_dm, false)) + if (!codec.encode_transmit_static_huffman_data_model(m_reference_encoding_dm, false)) return false; for (uint i = 0; i < 2; i++) { @@ -1901,10 +1831,10 @@ bool crn_comp::compress_internal() { codec.start_encoding(2 * 1024 * 1024); if (!pack_chunks( - m_mip_groups[mip_group].m_first_chunk, m_mip_groups[mip_group].m_num_chunks, - !pass && !mip_group, pass ? &codec : NULL, - m_has_comp[cColor] ? &endpoint_remap[0] : NULL, m_has_comp[cColor] ? &selector_remap[0] : NULL, - m_has_comp[cAlpha0] ? &endpoint_remap[1] : NULL, m_has_comp[cAlpha0] ? &selector_remap[1] : NULL)) { + mip_group, + !pass && !mip_group, pass ? &codec : NULL, + m_has_comp[cColor] ? &endpoint_remap[0] : NULL, m_has_comp[cColor] ? &selector_remap[0] : NULL, + m_has_comp[cAlpha0] ? &endpoint_remap[1] : NULL, m_has_comp[cAlpha0] ? &selector_remap[1] : NULL)) { return false; } @@ -1915,7 +1845,7 @@ bool crn_comp::compress_internal() { } if (!pass) { - m_chunk_encoding_dm.init(true, m_chunk_encoding_hist, 16); + m_reference_encoding_dm.init(true, m_chunk_encoding_hist, 16); for (uint i = 0; i < 2; i++) { if (m_endpoint_index_hist[i].size()) diff --git a/crnlib/crn_comp.h b/crnlib/crn_comp.h index d679e03..e427ca3 100644 --- a/crnlib/crn_comp.h +++ b/crnlib/crn_comp.h @@ -52,6 +52,7 @@ class crn_comp : public itexture_comp { uint m_first_chunk; uint m_num_chunks; + uint m_chunk_width; }; crnlib::vector m_mip_groups; @@ -66,9 +67,10 @@ class crn_comp : public itexture_comp { struct chunk_detail { chunk_detail() { utils::zero_object(*this); } - uint8 m_endpoint_references[cNumComps][2][2]; - uint16 m_endpoint_indices[cNumComps][2][2]; - uint16 m_selector_indices[cNumComps][2][2]; + uint16 m_endpoint_indices[2][2][cNumComps]; + uint16 m_selector_indices[2][2][cNumComps]; + uint8 m_endpoint_references[2][2]; + uint8 m_reference_group; }; crnlib::vector m_chunk_details; @@ -81,7 +83,7 @@ class crn_comp : public itexture_comp { dxt_hc m_hvq; symbol_histogram m_chunk_encoding_hist; - static_huffman_data_model m_chunk_encoding_dm; + static_huffman_data_model m_reference_encoding_dm; symbol_histogram m_endpoint_index_hist[2]; static_huffman_data_model m_endpoint_index_dm[2]; // color, alpha @@ -126,7 +128,7 @@ class crn_comp : public itexture_comp { void create_chunk_indices(); bool pack_chunks( - uint first_chunk, uint num_chunks, + uint group, bool clear_histograms, symbol_codec* pCodec, const crnlib::vector* pColor_endpoint_remap, diff --git a/inc/crn_decomp.h b/inc/crn_decomp.h index c7cd226..5145031 100644 --- a/inc/crn_decomp.h +++ b/inc/crn_decomp.h @@ -1638,10 +1638,6 @@ class symbol_codec { } // namespace crnd -#define CRND_HUFF_DECODE_BEGIN(x) -#define CRND_HUFF_DECODE_END(x) -#define CRND_HUFF_DECODE(codec, model, symbol) symbol = codec.decode(model); - namespace crnd { void crnd_assert(const char* pExp, const char* pFile, unsigned line) { char buf[512]; @@ -2773,16 +2769,7 @@ uint32 symbol_codec::decode(const static_huffman_data_model& model) { } uint64 symbol_codec::stop_decoding() { -#if 0 - uint32 i = get_bits(4); - uint32 k = get_bits(3); - i, k; - CRND_ASSERT((i == 15) && (k == 3)); -#endif - - uint64 n = static_cast(m_pDecode_buf_next - m_pDecode_buf); - - return n; + return static_cast(m_pDecode_buf_next - m_pDecode_buf); } } // namespace crnd @@ -3036,16 +3023,6 @@ uint32 dxt5_block::get_block_values(uint32* pDst, uint32 l, uint32 h) { // File: crnd_decode.cpp namespace crnd { -static uint8 g_crnd_endpoint_references[8][2][2] = { - {{0, 1}, {2, 1}}, - {{0, 1}, {0, 1}}, - {{0, 0}, {2, 2}}, - {{0, 1}, {0, 0}}, - {{0, 0}, {0, 1}}, - {{0, 0}, {2, 0}}, - {{0, 0}, {0, 2}}, - {{0, 0}, {0, 0}}, -}; class crn_unpacker { public: @@ -3168,7 +3145,7 @@ class crn_unpacker { symbol_codec m_codec; - static_huffman_data_model m_chunk_encoding_dm; + static_huffman_data_model m_reference_encoding_dm; static_huffman_data_model m_endpoint_delta_dm[2]; static_huffman_data_model m_selector_delta_dm[2]; @@ -3177,12 +3154,20 @@ class crn_unpacker { crnd::vector m_alpha_endpoints; crnd::vector m_alpha_selectors; + + struct block_buffer_element { + uint16 endpoint_reference; + uint16 color_endpoint_index; + uint16 alpha0_endpoint_index; + uint16 alpha1_endpoint_index; + }; + crnd::vector m_block_buffer; bool init_tables() { if (!m_codec.start_decoding(m_pData + m_pHeader->m_tables_ofs, m_pHeader->m_tables_size)) return false; - if (!m_codec.decode_receive_static_data_model(m_chunk_encoding_dm)) + if (!m_codec.decode_receive_static_data_model(m_reference_encoding_dm)) return false; if ((!m_pHeader->m_color_endpoints.m_num) && (!m_pHeader->m_alpha_endpoints.m_num)) @@ -3244,29 +3229,16 @@ class crn_unpacker { uint32* CRND_RESTRICT pDst = &m_color_endpoints[0]; - CRND_HUFF_DECODE_BEGIN(m_codec); - for (uint32 i = 0; i < num_color_endpoints; i++) { - uint32 da, db, dc, dd, de, df; - CRND_HUFF_DECODE(m_codec, dm[0], da); - a = (a + da) & 31; - CRND_HUFF_DECODE(m_codec, dm[1], db); - b = (b + db) & 63; - CRND_HUFF_DECODE(m_codec, dm[0], dc); - c = (c + dc) & 31; - - CRND_HUFF_DECODE(m_codec, dm[0], dd); - d = (d + dd) & 31; - CRND_HUFF_DECODE(m_codec, dm[1], de); - e = (e + de) & 63; - CRND_HUFF_DECODE(m_codec, dm[0], df); - f = (f + df) & 31; - + a = (a + m_codec.decode(dm[0])) & 31; + b = (b + m_codec.decode(dm[1])) & 63; + c = (c + m_codec.decode(dm[0])) & 31; + d = (d + m_codec.decode(dm[0])) & 31; + e = (e + m_codec.decode(dm[1])) & 63; + f = (f + m_codec.decode(dm[0])) & 31; *pDst++ = c | (b << 5U) | (a << 11U) | (f << 16U) | (e << 21U) | (d << 27U); } - CRND_HUFF_DECODE_END(m_codec); - m_codec.stop_decoding(); return true; @@ -3308,13 +3280,9 @@ class crn_unpacker { const uint8* pFrom_linear = g_dxt1_from_linear; - CRND_HUFF_DECODE_BEGIN(m_codec); - for (uint32 i = 0; i < num_color_selectors; i++) { for (uint32 j = 0; j < 8; j++) { - int32 sym; - CRND_HUFF_DECODE(m_codec, dm, sym); - + int32 sym = m_codec.decode(dm); cur[j * 2 + 0] = (delta0[sym] + cur[j * 2 + 0]) & 3; cur[j * 2 + 1] = (delta1[sym] + cur[j * 2 + 1]) & 3; } @@ -3326,8 +3294,6 @@ class crn_unpacker { (pFrom_linear[cur[12]] << 24) | (pFrom_linear[cur[13]] << 26) | (pFrom_linear[cur[14]] << 28) | (pFrom_linear[cur[15]] << 30); } - CRND_HUFF_DECODE_END(m_codec); - m_codec.stop_decoding(); return true; @@ -3349,22 +3315,12 @@ class crn_unpacker { uint16* CRND_RESTRICT pDst = &m_alpha_endpoints[0]; uint32 a = 0, b = 0; - CRND_HUFF_DECODE_BEGIN(m_codec); - for (uint32 i = 0; i < num_alpha_endpoints; i++) { - uint sa; - CRND_HUFF_DECODE(m_codec, dm, sa); - uint sb; - CRND_HUFF_DECODE(m_codec, dm, sb); - - a = (sa + a) & 255; - b = (sb + b) & 255; - + a = (a + m_codec.decode(dm)) & 255; + b = (b + m_codec.decode(dm)) & 255; *pDst++ = (uint16)(a | (b << 8)); } - CRND_HUFF_DECODE_END(m_codec); - m_codec.stop_decoding(); return true; @@ -3406,29 +3362,13 @@ class crn_unpacker { const uint8* pFrom_linear = g_dxt5_from_linear; - CRND_HUFF_DECODE_BEGIN(m_codec); - for (uint32 i = 0; i < num_alpha_selectors; i++) { for (uint32 j = 0; j < 8; j++) { - int32 sym; - CRND_HUFF_DECODE(m_codec, dm, sym); - + int32 sym = m_codec.decode(dm); cur[j * 2 + 0] = (delta0[sym] + cur[j * 2 + 0]) & 7; cur[j * 2 + 1] = (delta1[sym] + cur[j * 2 + 1]) & 7; - //cur[j*2+0] = ((sym%15)-7 + cur[j*2+0]) & 7; - //cur[j*2+1] = ((sym/15)-7 + cur[j*2+1]) & 7; } -#if 0 - dxt5_block blk; - for (uint32 y = 0; y < 4; y++) - for (uint32 x = 0; x < 4; x++) - blk.set_selector(x, y, pFrom_linear[cur[x+y*4]]); - - *pDst++ = blk.get_selectors_as_word(0); - *pDst++ = blk.get_selectors_as_word(1); - *pDst++ = blk.get_selectors_as_word(2); -#else *pDst++ = (uint16)((pFrom_linear[cur[0]]) | (pFrom_linear[cur[1]] << 3) | (pFrom_linear[cur[2]] << 6) | (pFrom_linear[cur[3]] << 9) | (pFrom_linear[cur[4]] << 12) | (pFrom_linear[cur[5]] << 15)); @@ -3437,11 +3377,8 @@ class crn_unpacker { *pDst++ = (uint16)((pFrom_linear[cur[10]] >> 2) | (pFrom_linear[cur[11]] << 1) | (pFrom_linear[cur[12]] << 4) | (pFrom_linear[cur[13]] << 7) | (pFrom_linear[cur[14]] << 10) | (pFrom_linear[cur[15]] << 13)); -#endif } - CRND_HUFF_DECODE_END(m_codec); - m_codec.stop_decoding(); return true; @@ -3474,408 +3411,249 @@ class crn_unpacker { } bool unpack_dxt1(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y) { - dst_size_in_bytes; - - uint32 chunk_encoding_bits = 1; - const uint32 num_color_endpoints = m_color_endpoints.size(); const uint32 num_color_selectors = m_color_selectors.size(); + const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (chunks_x << 2); - uint32 color_endpoint_index[2][2] = {}; - uint32 color_selector_index[2][2] = {}; + if (m_block_buffer.size() < chunks_x << 1) + m_block_buffer.resize(chunks_x << 1); - const uint32 num_faces = m_pHeader->m_faces; + uint32 color_endpoint_index = 0; + uint32 color_selector_index = 0; + uint8 reference_group = 0; - const uint32 row_pitch_in_dwords = row_pitch_in_bytes >> 2U; - - const int32 cBytesPerBlock = 8; - - CRND_HUFF_DECODE_BEGIN(m_codec); - - for (uint32 f = 0; f < num_faces; f++) { - uint8* CRND_RESTRICT pRow = pDst[f]; - - for (uint32 y = 0; y < chunks_y; y++) { - int32 block_delta = cBytesPerBlock * 2; - uint8* CRND_RESTRICT pBlock = pRow; - const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1); - - for (uint32 x = 0; x < chunks_x; x++) { - - if (chunk_encoding_bits == 1) { - CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits); - chunk_encoding_bits |= 512; + for (uint32 f = 0; f < m_pHeader->m_faces; f++) { + uint32* pData = (uint32*)pDst[f]; + for (uint32 y = 0; y < chunks_y << 1; y++, pData += delta_pitch_in_dwords) { + bool visible = y < blocks_y; + for (uint32 x = 0; x < chunks_x << 1; x++, pData += 2) { + visible = visible && x < blocks_x; + if (!(y & 1) && !(x & 1)) + reference_group = m_codec.decode(m_reference_encoding_dm); + block_buffer_element &buffer = m_block_buffer[x]; + uint8 endpoint_reference; + if (y & 1) { + endpoint_reference = buffer.endpoint_reference; + } else { + endpoint_reference = reference_group & 3; + reference_group >>= 2; + buffer.endpoint_reference = reference_group & 3; + reference_group >>= 2; } - - const uint32 chunk_encoding_index = chunk_encoding_bits & 7; - chunk_encoding_bits >>= 3; - - for (uint32 by = 0; by < 2; by++) { - for (uint32 bx = 0; bx < 2; bx++) { - uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx]; - if (!endpoint_reference) { - uint32 delta; - CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[0], delta); - color_endpoint_index[by][bx] = color_endpoint_index[by][bx ^ 1] + delta; - if (color_endpoint_index[by][bx] >= num_color_endpoints) - color_endpoint_index[by][bx] -= num_color_endpoints; - } else { - color_endpoint_index[by][bx] = endpoint_reference == 1 ? color_endpoint_index[by][bx ^ 1] : color_endpoint_index[by ^ 1][bx]; - } - } + if (!endpoint_reference) { + color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]); + if (color_endpoint_index >= num_color_endpoints) + color_endpoint_index -= num_color_endpoints; + buffer.color_endpoint_index = color_endpoint_index; + } else if (endpoint_reference == 1) { + buffer.color_endpoint_index = color_endpoint_index; + } else { + color_endpoint_index = buffer.color_endpoint_index; } - - const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1)); - - uint32* CRND_RESTRICT pD = (uint32*)pBlock; - - for (uint32 by = 0; by < 2; by++) { - pD = (uint32*)((uint8*)pBlock + row_pitch_in_bytes * by); - for (uint32 bx = 0; bx < 2; bx++, pD += 2) { - uint32 delta; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta); - color_selector_index[by][bx] = color_selector_index[by][bx ^ 1] + delta; - if (color_selector_index[by][bx] >= num_color_selectors) - color_selector_index[by][bx] -= num_color_selectors; - if (!((bx && skip_right_col) || (by && skip_bottom_row))) { - pD[0] = m_color_endpoints[color_endpoint_index[by][bx]]; - pD[1] = m_color_selectors[color_selector_index[by][bx]]; - } - } + color_selector_index += m_codec.decode(m_selector_delta_dm[0]); + if (color_selector_index >= num_color_selectors) + color_selector_index -= num_color_selectors; + if (visible) { + pData[0] = m_color_endpoints[color_endpoint_index]; + pData[1] = m_color_selectors[color_selector_index]; } - - pBlock += block_delta; - - } // x - - pRow += row_pitch_in_bytes * 2; - - } // y - - } // f - - CRND_HUFF_DECODE_END(m_codec); - + } + } + } return true; } bool unpack_dxt5(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y) { - dst_size_in_bytes; - - uint32 chunk_encoding_bits = 1; - const uint32 num_color_endpoints = m_color_endpoints.size(); const uint32 num_color_selectors = m_color_selectors.size(); const uint32 num_alpha_endpoints = m_alpha_endpoints.size(); const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num; + const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (chunks_x << 3); - uint32 color_endpoint_index[2][2] = {}; - uint32 color_selector_index[2][2] = {}; - uint32 alpha_endpoint_index[2][2] = {}; - uint32 alpha_selector_index[2][2] = {}; + if (m_block_buffer.size() < chunks_x << 1) + m_block_buffer.resize(chunks_x << 1); - const uint32 num_faces = m_pHeader->m_faces; + uint32 color_endpoint_index = 0; + uint32 color_selector_index = 0; + uint32 alpha0_endpoint_index = 0; + uint32 alpha0_selector_index = 0; + uint8 reference_group = 0; - //const uint32 row_pitch_in_dwords = row_pitch_in_bytes >> 2U; - - const int32 cBytesPerBlock = 16; - - CRND_HUFF_DECODE_BEGIN(m_codec); - - for (uint32 f = 0; f < num_faces; f++) { - uint8* CRND_RESTRICT pRow = pDst[f]; - - for (uint32 y = 0; y < chunks_y; y++) { - int32 block_delta = cBytesPerBlock * 2; - uint8* CRND_RESTRICT pBlock = pRow; - const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1); - - for (uint32 x = 0; x < chunks_x; x++) { - uint32 color_endpoints[2][2]; - uint32 alpha_endpoints[2][2]; - - if (chunk_encoding_bits == 1) { - CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits); - chunk_encoding_bits |= 512; + for (uint32 f = 0; f < m_pHeader->m_faces; f++) { + uint32* pData = (uint32*)pDst[f]; + for (uint32 y = 0; y < chunks_y << 1; y++, pData += delta_pitch_in_dwords) { + bool visible = y < blocks_y; + for (uint32 x = 0; x < chunks_x << 1; x++, pData += 4) { + visible = visible && x < blocks_x; + if (!(y & 1) && !(x & 1)) + reference_group = m_codec.decode(m_reference_encoding_dm); + block_buffer_element &buffer = m_block_buffer[x]; + uint8 endpoint_reference; + if (y & 1) { + endpoint_reference = buffer.endpoint_reference; + } else { + endpoint_reference = reference_group & 3; + reference_group >>= 2; + buffer.endpoint_reference = reference_group & 3; + reference_group >>= 2; } - - const uint32 chunk_encoding_index = chunk_encoding_bits & 7; - chunk_encoding_bits >>= 3; - - const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1)); - - uint32* CRND_RESTRICT pD = (uint32*)pBlock; - - for (uint32 by = 0; by < 2; by++) { - for (uint32 bx = 0; bx < 2; bx++) { - uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx]; - if (!endpoint_reference) { - uint32 delta; - CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta); - alpha_endpoint_index[by][bx] = alpha_endpoint_index[by][bx ^ 1] + delta; - if (alpha_endpoint_index[by][bx] >= num_alpha_endpoints) - alpha_endpoint_index[by][bx] -= num_alpha_endpoints; - } else { - alpha_endpoint_index[by][bx] = endpoint_reference == 1 ? alpha_endpoint_index[by][bx ^ 1] : alpha_endpoint_index[by ^ 1][bx]; - } - } + if (!endpoint_reference) { + color_endpoint_index += m_codec.decode(m_endpoint_delta_dm[0]); + if (color_endpoint_index >= num_color_endpoints) + color_endpoint_index -= num_color_endpoints; + buffer.color_endpoint_index = color_endpoint_index; + alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]); + if (alpha0_endpoint_index >= num_alpha_endpoints) + alpha0_endpoint_index -= num_alpha_endpoints; + buffer.alpha0_endpoint_index = alpha0_endpoint_index; + } else if (endpoint_reference == 1) { + buffer.color_endpoint_index = color_endpoint_index; + buffer.alpha0_endpoint_index = alpha0_endpoint_index; + } else { + color_endpoint_index = buffer.color_endpoint_index; + alpha0_endpoint_index = buffer.alpha0_endpoint_index; } - - for (uint32 by = 0; by < 2; by++) { - for (uint32 bx = 0; bx < 2; bx++) { - uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx]; - if (!endpoint_reference) { - uint32 delta; - CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[0], delta); - color_endpoint_index[by][bx] = color_endpoint_index[by][bx ^ 1] + delta; - if (color_endpoint_index[by][bx] >= num_color_endpoints) - color_endpoint_index[by][bx] -= num_color_endpoints; - } else { - color_endpoint_index[by][bx] = endpoint_reference == 1 ? color_endpoint_index[by][bx ^ 1] : color_endpoint_index[by ^ 1][bx]; - } - } + color_selector_index += m_codec.decode(m_selector_delta_dm[0]); + if (color_selector_index >= num_color_selectors) + color_selector_index -= num_color_selectors; + alpha0_selector_index += m_codec.decode(m_selector_delta_dm[1]); + if (alpha0_selector_index >= num_alpha_selectors) + alpha0_selector_index -= num_alpha_selectors; + if (visible) { + const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3]; + pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16); + pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16); + pData[2] = m_color_endpoints[color_endpoint_index]; + pData[3] = m_color_selectors[color_selector_index]; } - - for (uint32 by = 0; by < 2; by++) { - for (uint32 bx = 0; bx < 2; bx++, pD += 4) { - uint32 delta0; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta0); - alpha_selector_index[by][bx] = alpha_selector_index[by][bx ^ 1] + delta0; - if (alpha_selector_index[by][bx] >= num_alpha_selectors) - alpha_selector_index[by][bx] -= num_alpha_selectors; - - uint32 delta1; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[0], delta1); - color_selector_index[by][bx] = color_selector_index[by][bx ^ 1] + delta1; - if (color_selector_index[by][bx] >= num_color_selectors) - color_selector_index[by][bx] -= num_color_selectors; - - if (!((bx && skip_right_col) || (by && skip_bottom_row))) { - const uint16* pAlpha_selectors = &m_alpha_selectors[alpha_selector_index[by][bx] * 3]; - pD[0] = m_alpha_endpoints[alpha_endpoint_index[by][bx]] | (pAlpha_selectors[0] << 16); - pD[1] = pAlpha_selectors[1] | (pAlpha_selectors[2] << 16); - pD[2] = m_color_endpoints[color_endpoint_index[by][bx]]; - pD[3] = m_color_selectors[color_selector_index[by][bx]]; - } - } - - pD = (uint32*)((uint8*)pD - cBytesPerBlock * 2 + row_pitch_in_bytes); - } - - pBlock += block_delta; - - } // x - - pRow += row_pitch_in_bytes * 2; - - } // y - - } // f - - CRND_HUFF_DECODE_END(m_codec); - + } + } + } return true; } bool unpack_dxn(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y) { - dst_size_in_bytes; - - uint32 chunk_encoding_bits = 1; - const uint32 num_alpha_endpoints = m_alpha_endpoints.size(); const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num; + const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (chunks_x << 3); - uint32 alpha0_endpoint_index[2][2] = {}; - uint32 alpha0_selector_index[2][2] = {}; - uint32 alpha1_endpoint_index[2][2] = {}; - uint32 alpha1_selector_index[2][2] = {}; + if (m_block_buffer.size() < chunks_x << 1) + m_block_buffer.resize(chunks_x << 1); - const uint32 num_faces = m_pHeader->m_faces; + uint32 alpha0_endpoint_index = 0; + uint32 alpha0_selector_index = 0; + uint32 alpha1_endpoint_index = 0; + uint32 alpha1_selector_index = 0; + uint8 reference_group = 0; - //const uint32 row_pitch_in_dwords = row_pitch_in_bytes >> 2U; - - const int32 cBytesPerBlock = 16; - - CRND_HUFF_DECODE_BEGIN(m_codec); - - for (uint32 f = 0; f < num_faces; f++) { - uint8* CRND_RESTRICT pRow = pDst[f]; - - for (uint32 y = 0; y < chunks_y; y++) { - int32 block_delta = cBytesPerBlock * 2; - uint8* CRND_RESTRICT pBlock = pRow; - const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1); - - for (uint32 x = 0; x < chunks_x; x++) { - if (chunk_encoding_bits == 1) { - CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits); - chunk_encoding_bits |= 512; + for (uint32 f = 0; f < m_pHeader->m_faces; f++) { + uint32* pData = (uint32*)pDst[f]; + for (uint32 y = 0; y < chunks_y << 1; y++, pData += delta_pitch_in_dwords) { + bool visible = y < blocks_y; + for (uint32 x = 0; x < chunks_x << 1; x++, pData += 4) { + visible = visible && x < blocks_x; + if (!(y & 1) && !(x & 1)) + reference_group = m_codec.decode(m_reference_encoding_dm); + block_buffer_element &buffer = m_block_buffer[x]; + uint8 endpoint_reference; + if (y & 1) { + endpoint_reference = buffer.endpoint_reference; + } else { + endpoint_reference = reference_group & 3; + reference_group >>= 2; + buffer.endpoint_reference = reference_group & 3; + reference_group >>= 2; } - - const uint32 chunk_encoding_index = chunk_encoding_bits & 7; - chunk_encoding_bits >>= 3; - - const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1)); - - uint32* CRND_RESTRICT pD = (uint32*)pBlock; - - for (uint32 by = 0; by < 2; by++) { - for (uint32 bx = 0; bx < 2; bx++) { - uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx]; - if (!endpoint_reference) { - uint32 delta; - CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta); - alpha0_endpoint_index[by][bx] = alpha0_endpoint_index[by][bx ^ 1] + delta; - if (alpha0_endpoint_index[by][bx] >= num_alpha_endpoints) - alpha0_endpoint_index[by][bx] -= num_alpha_endpoints; - } else { - alpha0_endpoint_index[by][bx] = endpoint_reference == 1 ? alpha0_endpoint_index[by][bx ^ 1] : alpha0_endpoint_index[by ^ 1][bx]; - } - } + if (!endpoint_reference) { + alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]); + if (alpha0_endpoint_index >= num_alpha_endpoints) + alpha0_endpoint_index -= num_alpha_endpoints; + buffer.alpha0_endpoint_index = alpha0_endpoint_index; + alpha1_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]); + if (alpha1_endpoint_index >= num_alpha_endpoints) + alpha1_endpoint_index -= num_alpha_endpoints; + buffer.alpha1_endpoint_index = alpha1_endpoint_index; + } else if (endpoint_reference == 1) { + buffer.alpha0_endpoint_index = alpha0_endpoint_index; + buffer.alpha1_endpoint_index = alpha1_endpoint_index; + } else { + alpha0_endpoint_index = buffer.alpha0_endpoint_index; + alpha1_endpoint_index = buffer.alpha1_endpoint_index; } - - for (uint32 by = 0; by < 2; by++) { - for (uint32 bx = 0; bx < 2; bx++) { - uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx]; - if (!endpoint_reference) { - uint32 delta; - CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta); - alpha1_endpoint_index[by][bx] = alpha1_endpoint_index[by][bx ^ 1] + delta; - if (alpha1_endpoint_index[by][bx] >= num_alpha_endpoints) - alpha1_endpoint_index[by][bx] -= num_alpha_endpoints; - } else { - alpha1_endpoint_index[by][bx] = endpoint_reference == 1 ? alpha1_endpoint_index[by][bx ^ 1] : alpha1_endpoint_index[by ^ 1][bx]; - } - } + alpha0_selector_index += m_codec.decode(m_selector_delta_dm[1]); + if (alpha0_selector_index >= num_alpha_selectors) + alpha0_selector_index -= num_alpha_selectors; + alpha1_selector_index += m_codec.decode(m_selector_delta_dm[1]); + if (alpha1_selector_index >= num_alpha_selectors) + alpha1_selector_index -= num_alpha_selectors; + if (visible) { + const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3]; + const uint16* pAlpha1_selectors = &m_alpha_selectors[alpha1_selector_index * 3]; + pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16); + pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16); + pData[2] = m_alpha_endpoints[alpha1_endpoint_index] | (pAlpha1_selectors[0] << 16); + pData[3] = pAlpha1_selectors[1] | (pAlpha1_selectors[2] << 16); } - - for (uint32 by = 0; by < 2; by++) { - for (uint32 bx = 0; bx < 2; bx++, pD += 4) { - uint32 delta0; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta0); - alpha0_selector_index[by][bx] = alpha0_selector_index[by][bx ^ 1] + delta0; - if (alpha0_selector_index[by][bx] >= num_alpha_selectors) - alpha0_selector_index[by][bx] -= num_alpha_selectors; - - uint32 delta1; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta1); - alpha1_selector_index[by][bx] = alpha1_selector_index[by][bx ^ 1] + delta1; - if (alpha1_selector_index[by][bx] >= num_alpha_selectors) - alpha1_selector_index[by][bx] -= num_alpha_selectors; - - if (!((bx && skip_right_col) || (by && skip_bottom_row))) { - const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index[by][bx] * 3]; - const uint16* pAlpha1_selectors = &m_alpha_selectors[alpha1_selector_index[by][bx] * 3]; - pD[0] = m_alpha_endpoints[alpha0_endpoint_index[by][bx]] | (pAlpha0_selectors[0] << 16); - pD[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16); - pD[2] = m_alpha_endpoints[alpha1_endpoint_index[by][bx]] | (pAlpha1_selectors[0] << 16); - pD[3] = pAlpha1_selectors[1] | (pAlpha1_selectors[2] << 16); - } - } - - pD = (uint32*)((uint8*)pD - cBytesPerBlock * 2 + row_pitch_in_bytes); - } - - pBlock += block_delta; - - } // x - - pRow += row_pitch_in_bytes * 2; - - } // y - - } // f - - CRND_HUFF_DECODE_END(m_codec); - + } + } + } return true; } bool unpack_dxt5a(uint8** pDst, uint32 dst_size_in_bytes, uint32 row_pitch_in_bytes, uint32 blocks_x, uint32 blocks_y, uint32 chunks_x, uint32 chunks_y) { - dst_size_in_bytes; - - uint32 chunk_encoding_bits = 1; - const uint32 num_alpha_endpoints = m_alpha_endpoints.size(); const uint32 num_alpha_selectors = m_pHeader->m_alpha_selectors.m_num; + const int32 delta_pitch_in_dwords = (row_pitch_in_bytes >> 2) - (chunks_x << 2); - uint32 alpha0_endpoint_index[2][2] = {}; - uint32 alpha0_selector_index[2][2] = {}; + if (m_block_buffer.size() < chunks_x << 1) + m_block_buffer.resize(chunks_x << 1); - const uint32 num_faces = m_pHeader->m_faces; + uint32 alpha0_endpoint_index = 0; + uint32 alpha0_selector_index = 0; + uint8 reference_group = 0; - const int32 cBytesPerBlock = 8; - - CRND_HUFF_DECODE_BEGIN(m_codec); - - for (uint32 f = 0; f < num_faces; f++) { - uint8* CRND_RESTRICT pRow = pDst[f]; - - for (uint32 y = 0; y < chunks_y; y++) { - int32 block_delta = cBytesPerBlock * 2; - uint8* CRND_RESTRICT pBlock = pRow; - const bool skip_bottom_row = (y == (chunks_y - 1)) && (blocks_y & 1); - - for (uint32 x = 0; x < chunks_x; x++) { - if (chunk_encoding_bits == 1) { - CRND_HUFF_DECODE(m_codec, m_chunk_encoding_dm, chunk_encoding_bits); - chunk_encoding_bits |= 512; + for (uint32 f = 0; f < m_pHeader->m_faces; f++) { + uint32* pData = (uint32*)pDst[f]; + for (uint32 y = 0; y < chunks_y << 1; y++, pData += delta_pitch_in_dwords) { + bool visible = y < blocks_y; + for (uint32 x = 0; x < chunks_x << 1; x++, pData += 2) { + visible = visible && x < blocks_x; + if (!(y & 1) && !(x & 1)) + reference_group = m_codec.decode(m_reference_encoding_dm); + block_buffer_element &buffer = m_block_buffer[x]; + uint8 endpoint_reference; + if (y & 1) { + endpoint_reference = buffer.endpoint_reference; + } else { + endpoint_reference = reference_group & 3; + reference_group >>= 2; + buffer.endpoint_reference = reference_group & 3; + reference_group >>= 2; } - - const uint32 chunk_encoding_index = chunk_encoding_bits & 7; - chunk_encoding_bits >>= 3; - - const bool skip_right_col = (blocks_x & 1) && (x == ((int32)chunks_x - 1)); - - uint32* CRND_RESTRICT pD = (uint32*)pBlock; - - for (uint32 by = 0; by < 2; by++) { - for (uint32 bx = 0; bx < 2; bx++) { - uint8 endpoint_reference = g_crnd_endpoint_references[chunk_encoding_index][by][bx]; - if (!endpoint_reference) { - uint32 delta; - CRND_HUFF_DECODE(m_codec, m_endpoint_delta_dm[1], delta); - alpha0_endpoint_index[by][bx] = alpha0_endpoint_index[by][bx ^ 1] + delta; - if (alpha0_endpoint_index[by][bx] >= num_alpha_endpoints) - alpha0_endpoint_index[by][bx] -= num_alpha_endpoints; - } else { - alpha0_endpoint_index[by][bx] = endpoint_reference == 1 ? alpha0_endpoint_index[by][bx ^ 1] : alpha0_endpoint_index[by ^ 1][bx]; - } - } + if (!endpoint_reference) { + alpha0_endpoint_index += m_codec.decode(m_endpoint_delta_dm[1]); + if (alpha0_endpoint_index >= num_alpha_endpoints) + alpha0_endpoint_index -= num_alpha_endpoints; + buffer.alpha0_endpoint_index = alpha0_endpoint_index; + } else if (endpoint_reference == 1) { + buffer.alpha0_endpoint_index = alpha0_endpoint_index; + } else { + alpha0_endpoint_index = buffer.alpha0_endpoint_index; } - - for (uint32 by = 0; by < 2; by++) { - for (uint32 bx = 0; bx < 2; bx++, pD += 2) { - uint32 delta; - CRND_HUFF_DECODE(m_codec, m_selector_delta_dm[1], delta); - alpha0_selector_index[by][bx] = alpha0_selector_index[by][bx ^ 1] + delta; - if (alpha0_selector_index[by][bx] >= num_alpha_selectors) - alpha0_selector_index[by][bx] -= num_alpha_selectors; - - if (!((bx && skip_right_col) || (by && skip_bottom_row))) { - const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index[by][bx] * 3]; - pD[0] = m_alpha_endpoints[alpha0_endpoint_index[by][bx]] | (pAlpha0_selectors[0] << 16); - pD[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16); - } - } - - pD = (uint32*)((uint8*)pD - cBytesPerBlock * 2 + row_pitch_in_bytes); + alpha0_selector_index += m_codec.decode(m_selector_delta_dm[1]); + if (alpha0_selector_index >= num_alpha_selectors) + alpha0_selector_index -= num_alpha_selectors; + if (visible) { + const uint16* pAlpha0_selectors = &m_alpha_selectors[alpha0_selector_index * 3]; + pData[0] = m_alpha_endpoints[alpha0_endpoint_index] | (pAlpha0_selectors[0] << 16); + pData[1] = pAlpha0_selectors[1] | (pAlpha0_selectors[2] << 16); } - - pBlock += block_delta; - - } // x - - pRow += row_pitch_in_bytes * 2; - - } // y - - } // f - - CRND_HUFF_DECODE_END(m_codec); - + } + } + } return true; } + }; crnd_unpack_context crnd_unpack_begin(const void* pData, uint32 data_size) {