Exemplo n.º 1
0
Arquivo: cff.cpp Projeto: EQ4/adplug
/*
  Lempel-Ziv-Tyr ;-)
*/
long CcffLoader::cff_unpacker::unpack(unsigned char *ibuf, unsigned char *obuf)
{
  if (memcmp(ibuf,"YsComp""\x07""CUD1997""\x1A\x04",16))
    return 0;

  input = ibuf + 16;
  output = obuf;

  output_length = 0;

  heap = (unsigned char *)malloc(0x10000);
  dictionary = (unsigned char **)malloc(sizeof(unsigned char *)*0x8000);

  memset(heap,0,0x10000);
  memset(dictionary,0,0x8000);

  cleanup();
  if(!startup())
    goto out;

  // LZW
  while (1)
    {
      new_code = get_code();

      // 0x00: end of data
      if (new_code == 0)
	break;

      // 0x01: end of block
      if (new_code == 1)
	{
	  cleanup();
	  if(!startup())
	    goto out;

	  continue;
	}

      // 0x02: expand code length
      if (new_code == 2)
	{
	  code_length++;

	  continue;
	}

      // 0x03: RLE
      if (new_code == 3)
	{
	  unsigned char old_code_length = code_length;

	  code_length = 2;

	  unsigned char repeat_length = get_code() + 1;

	  code_length = 4 << get_code();

	  unsigned long repeat_counter = get_code();

	  if(output_length + repeat_counter * repeat_length > 0x10000) {
	    output_length = 0;
	    goto out;
	  }

	  for (unsigned int i=0;i<repeat_counter*repeat_length;i++)
	    output[output_length++] = output[output_length - repeat_length];

	  code_length = old_code_length;

	  if(!startup())
	    goto out;

	  continue;
	}

      if (new_code >= (0x104 + dictionary_length))
	{
	  // dictionary <- old.code.string + old.code.char
	  the_string[++the_string[0]] = the_string[1];
	}
      else
	{
	  // dictionary <- old.code.string + new.code.char
	  unsigned char temp_string[256];

	  translate_code(new_code,temp_string);

	  the_string[++the_string[0]] = temp_string[1];
	}

      expand_dictionary(the_string);

      // output <- new.code.string
      translate_code(new_code,the_string);

      if(output_length + the_string[0] > 0x10000) {
	output_length = 0;
	goto out;
      }

      for (int i=0;i<the_string[0];i++)
	output[output_length++] = the_string[i+1];

      old_code = new_code;
    }

 out:
  free(heap);
  free(dictionary);
  return output_length;
}
Exemplo n.º 2
0
/*
  Lempel-Ziv-Tyr ;-)
*/
void CffPlayer::cff_unpacker::unpack(const std::vector<uint8_t>& ibuf, std::vector<uint8_t>& obuf)
{
    obuf.clear();

    if(memcmp(ibuf.data(), "YsComp"
              "\x07"
              "CUD1997"
              "\x1A\x04",
              16))
        return;

    auto it = std::next(ibuf.begin(), 16);

    std::vector<std::vector<uint8_t>> dictionary;
    cleanup();
    if(!startup(dictionary, obuf, it))
        return;

    // LZW
    while(auto newCode = get_code(it))
    {
        // 0x01: end of block
        if(newCode == 1)
        {
            cleanup();
            dictionary.clear();
            if(!startup(dictionary, obuf, it))
                return;

            continue;
        }

        // 0x02: expand code length
        if(newCode == 2)
        {
            m_codeLength++;

            continue;
        }

        // 0x03: RLE
        if(newCode == 3)
        {
            uint8_t old_code_length = m_codeLength;

            m_codeLength = 2;

            uint8_t repeat_length = get_code(it) + 1;

            m_codeLength = 4 << get_code(it);

            unsigned long repeat_counter = get_code(it);

            if(obuf.size() + repeat_counter * repeat_length)
            {
                obuf.clear();
                return;
            }

            for(auto i = 0; i < repeat_counter * repeat_length; i++)
            {
                obuf.emplace_back(obuf[obuf.size() - repeat_length]);
            }

            m_codeLength = old_code_length;

            if(!startup(dictionary, obuf, it))
                return;

            continue;
        }

        if(newCode >= (0x104 + dictionary.size()))
        {
            // dictionary <- old.code.string + old.code.char
            m_theString[++m_theString[0]] = m_theString[1];
        }
        else
        {
            // dictionary <- old.code.string + new.code.char
            uint8_t temp_string[256];

            translate_code(newCode, temp_string, dictionary);

            m_theString[++m_theString[0]] = temp_string[1];
        }

        expand_dictionary(m_theString, dictionary);

        // output <- new.code.string
        translate_code(newCode, m_theString, dictionary);

        for(int i = 0; i < m_theString[0]; i++)
            obuf.emplace_back(m_theString[i + 1]);
    }
}