Esempio n. 1
0
    Formats::Chiptune::Container::Ptr Parse(const Binary::Container& data, Builder& target)
    {
      if (!FastCheck(data))
      {
        return Formats::Chiptune::Container::Ptr();
      }
      try
      {
        Binary::InputStream stream(data);
        stream.ReadField<SignatureType>();
        target.SetTitle(DecodeString(stream.ReadCString(MAX_STRING_SIZE)));
        target.SetAuthor(DecodeString(stream.ReadCString(MAX_STRING_SIZE)));
        target.SetComment(DecodeString(stream.ReadCString(MAX_COMMENT_SIZE)));

        const std::size_t fixedOffset = stream.GetPosition();
        std::size_t totalFrames = 0;
        for (;;)
        {
          const uint8_t val = stream.ReadField<uint8_t>();
          if (val == FINISH)
          {
            break;
          }
          switch (val)
          {
          case BEGIN_FRAME:
            ++totalFrames;
            target.BeginFrames(1);
            break;
          case SKIP_FRAMES:
            {
              const uint_t frames = 3 + stream.ReadField<uint8_t>();
              totalFrames += frames;
              target.BeginFrames(frames);
            }
            break;
          case SELECT_SECOND_CHIP:
            target.SelectChip(1);
            break;
          case SELECT_FIRST_CHIP:
            target.SelectChip(0);
            break;
          case LOOP_MARKER:
            target.SetLoop();
            break;
          default:
            target.SetRegister(val, stream.ReadField<uint8_t>());
            break;
          }
        }
        Require(totalFrames >= MIN_FRAMES);
        const std::size_t usedSize = stream.GetPosition();
        const auto subData = stream.GetReadData();
        return CreateCalculatingCrcContainer(subData, fixedOffset, usedSize - fixedOffset);
      }
      catch (const std::exception&)
      {
        return Formats::Chiptune::Container::Ptr();
      }
    }
Esempio n. 2
0
    Formats::Chiptune::Container::Ptr Parse(const Binary::Container& rawData, Builder& target)
    {
      if (!FastCheck(rawData))
      {
        return Formats::Chiptune::Container::Ptr();
      }

      const Binary::TypedContainer& data(rawData);
      const Header& header = *data.GetField<Header>(0);
      //workaround for some emulators
      const std::size_t offset = (header.Version == INT_BEGIN) ? offsetof(Header, Version) : sizeof(header);
      std::size_t restSize = rawData.Size() - offset;
      const uint8_t* bdata = data.GetField<uint8_t>(offset);
      //detect as much chunks as possible, in despite of real format issues
      while (restSize)
      {
        const uint_t reg = *bdata;
        ++bdata;
        --restSize;
        if (INT_BEGIN == reg)
        {
          target.AddChunks(1);
        }
        else if (INT_SKIP == reg)
        {
          if (restSize < 1)
          {
            ++restSize;//put byte back
            break;
          }
          target.AddChunks(4 * *bdata);
          ++bdata;
          --restSize;
        }
        else if (MUS_END == reg)
        {
          break;
        }
        else if (reg <= 15) //register
        {
          if (restSize < 1)
          {
            ++restSize;//put byte back
            break;
          }
          target.SetRegister(reg, *bdata);
          ++bdata;
          --restSize;
        }
        else
        {
          ++restSize;//put byte back
          break;
        }
      }
      const std::size_t usedSize = rawData.Size() - restSize;
      const Binary::Container::Ptr subData = rawData.GetSubcontainer(0, usedSize);
      return CreateCalculatingCrcContainer(subData, offset, usedSize - offset);
    }