Exemple #1
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);
    }
Exemple #2
0
Archived::Container::Ptr ParseArchive(const Packed::Decoder& decoder, const Binary::Container& data)
{
    const TRDos::CatalogueBuilder::Ptr builder = TRDos::CatalogueBuilder::CreateGeneric();
    const std::size_t archSize = data.Size();
    std::size_t rawOffset = 0;
    for (std::size_t flatOffset = 0; rawOffset < archSize;)
    {
        const Binary::Container::Ptr rawData = data.GetSubcontainer(rawOffset, archSize - rawOffset);
        const Formats::Packed::Container::Ptr fileData = decoder.Decode(*rawData);
        if (!fileData)
        {
            break;
        }
        const String fileName = ExtractFileName(rawData->Start());
        const std::size_t fileSize = fileData->Size();
        const std::size_t usedSize = fileData->PackedSize();
        const TRDos::File::Ptr file = TRDos::File::Create(fileData, fileName, flatOffset, fileSize);
        builder->AddFile(file);
        rawOffset += usedSize;
        flatOffset += fileSize;
    }
    if (rawOffset)
    {
        builder->SetRawData(data.GetSubcontainer(0, rawOffset));
        return builder->GetResult();
    }
    else
    {
        return Archived::Container::Ptr();
    }
}
Exemple #3
0
 bool FastCheck(const Binary::Container& rawData)
 {
   if (rawData.Size() < MIN_SIZE)
   {
     return false;
   }
   const SignatureType& sign = *static_cast<const SignatureType*>(rawData.Start());
   return sign == SIGNATURE;
 }
Exemple #4
0
 std::size_t Parse(const Binary::Container& rawData, ImageVisitor& visitor)
 {
   SourceStream stream(rawData);
   try
   {
     const RawHeader& header = stream.Get<RawHeader>();
     const uint_t id = fromLE(header.ID);
     Require(id == ID_OLD || id == ID_NEW);
     Require(header.Sequence == 0);
     Require(Math::InRange<uint_t>(header.Sides, MIN_SIDES_COUNT, MAX_SIDES_COUNT));
     if (header.HasComment())
     {
       const RawComment& comment = stream.Get<RawComment>();
       if (const std::size_t size = fromLE(comment.Size))
       {
         stream.GetData(size);
       }
     }
     const bool compressedData = id == ID_NEW;
     const bool newCompression = header.Version > 20;
     if (compressedData)
     {
       if (!newCompression)
       {
         Dbg("Old compression is not supported.");
         return 0;
       }
       const std::size_t packedSize = rawData.Size() - sizeof(header);
       const Binary::Container::Ptr packed = rawData.GetSubcontainer(sizeof(header), packedSize);
       if (const Formats::Packed::Container::Ptr fullDecoded = 
         Formats::Packed::Lha::DecodeRawDataAtLeast(*packed, COMPRESSION_ALGORITHM, MAX_IMAGE_SIZE))
       {
         SourceStream subStream(*fullDecoded);
         ParseSectors(subStream, visitor);
         const std::size_t usedInPacked = subStream.GetOffset();
         Dbg("Used %1% bytes in packed stream", usedInPacked);
         if (const Formats::Packed::Container::Ptr decoded =
           Formats::Packed::Lha::DecodeRawDataAtLeast(*packed, COMPRESSION_ALGORITHM, usedInPacked))
         {
           const std::size_t usedSize = decoded->PackedSize();
           return sizeof(header) + usedSize;
         }
       }
       Dbg("Failed to decode lha stream");
       return 0;
     }
     else
     {
       ParseSectors(stream, visitor);
     }
     return stream.GetOffset();
   }
   catch (const std::exception&)
   {
     return 0;
   }
 }
Exemple #5
0
 Formats::Chiptune::Container::Ptr Decode(const Binary::Container& rawData) const override
 {
   if (!Format->Match(rawData))
   {
     return Formats::Chiptune::Container::Ptr();
   }
   const std::size_t realSize = std::min(rawData.Size(), MAX_SIZE);
   const Binary::Container::Ptr data = rawData.GetSubcontainer(0, realSize);
   return CreateCalculatingCrcContainer(data, 0, realSize);
 }
Exemple #6
0
 bool FastCheck(const Binary::Container& rawData)
 {
   if (rawData.Size() <= sizeof(Header))
   {
     return false;
   }
   const Header* const header = static_cast<const Header*>(rawData.Start());
   return 0 == std::memcmp(header->Sign, SIGNATURE, sizeof(SIGNATURE)) &&
      MARKER == header->Marker;
 }
Exemple #7
0
 virtual Container::Ptr Decode(const Binary::Container& rawData) const
 {
   const void* const data = rawData.Start();
   const std::size_t availSize = rawData.Size();
   const FullDiskImage::Container container(data, availSize);
   if (!container.FastCheck())
   {
     return Container::Ptr();
   }
   FullDiskImage::Decoder decoder(container);
   return CreatePackedContainer(decoder.GetResult(), decoder.GetUsedSize());
 }
Exemple #8
0
 virtual Container::Ptr Decode(const Binary::Container& rawData) const
 {
   if (!Depacker->Match(rawData))
   {
     return Container::Ptr();
   }
   const MSPack::Container container(rawData.Start(), rawData.Size());
   if (!container.FastCheck())
   {
     return Container::Ptr();
   }
   MSPack::DataDecoder decoder(container);
   return CreatePackedContainer(decoder.GetResult(), container.GetUsedSize());
 }
Exemple #9
0
 virtual Container::Ptr Decode(const Binary::Container& rawData) const
 {
   if (!Player->Match(rawData))
   {
     return Container::Ptr();
   }
   const Binary::TypedContainer typedData(rawData);
   const std::size_t availSize = rawData.Size();
   const std::size_t playerSize = CompiledPT24::PLAYER_SIZE;
   const CompiledPT24::Player& rawPlayer = *typedData.GetField<CompiledPT24::Player>(0);
   const uint_t dataAddr = fromLE(rawPlayer.DataAddr);
   if (dataAddr < playerSize)
   {
     Dbg("Invalid compile addr");
     return Container::Ptr();
   }
   const CompiledPT24::RawHeader& rawHeader = *typedData.GetField<CompiledPT24::RawHeader>(playerSize);
   const uint_t patternsCount = CompiledPT24::GetPatternsCount(rawHeader, availSize - playerSize);
   if (!patternsCount)
   {
     Dbg("Invalid patterns count");
     return Container::Ptr();
   }
   const uint_t compileAddr = dataAddr - playerSize;
   Dbg("Detected player compiled at %1% (#%1$04x) with %2% patterns", compileAddr, patternsCount);
   const std::size_t modDataSize = std::min(CompiledPT24::MAX_MODULE_SIZE, availSize - playerSize);
   const Binary::Container::Ptr modData = rawData.GetSubcontainer(playerSize, modDataSize);
   const Formats::Chiptune::PatchedDataBuilder::Ptr builder = Formats::Chiptune::PatchedDataBuilder::Create(*modData);
   //fix samples/ornaments offsets
   for (uint_t idx = offsetof(CompiledPT24::RawHeader, SamplesOffsets); idx != offsetof(CompiledPT24::RawHeader, PatternsOffset); idx += 2)
   {
     builder->FixLEWord(idx, -int_t(dataAddr));
   }
   //fix patterns offsets
   for (uint_t idx = fromLE(rawHeader.PatternsOffset), lim = idx + 6 * patternsCount; idx != lim; idx += 2)
   {
     builder->FixLEWord(idx, -int_t(dataAddr));
   }
   const Binary::Container::Ptr fixedModule = builder->GetResult();
   if (Formats::Chiptune::Container::Ptr fixedParsed = Decoder->Decode(*fixedModule))
   {
     return CreatePackedContainer(fixedParsed, playerSize + fixedParsed->Size());
   }
   Dbg("Failed to parse fixed module");
   return Container::Ptr();
 }
Exemple #10
0
    Module::Holder::Ptr CreateModule(const Parameters::Accessor& params, const Binary::Container& rawData, Parameters::Container::Ptr properties) const override
    {
      try
      {
        const TunePtr tune = std::make_shared<SidTune>(static_cast<const uint_least8_t*>(rawData.Start()),
          static_cast<uint_least32_t>(rawData.Size()));
        CheckSidplayError(tune->getStatus());
        const unsigned songIdx = tune->selectSong(0);

        const SidTuneInfo& tuneInfo = *tune->getInfo();
        if (tuneInfo.songs() > 1)
        {
          Require(HasSidContainer(*properties));
        }

        PropertiesHelper props(*properties);
        switch (tuneInfo.numberOfInfoStrings())
        {
        default:
        case 3:
          //copyright/publisher really
          props.SetComment(FromStdString(tuneInfo.infoString(2)));
        case 2:
          props.SetAuthor(FromStdString(tuneInfo.infoString(1)));
        case 1:
          props.SetTitle(FromStdString(tuneInfo.infoString(0)));
        case 0:
          break;
        }
        const Binary::Container::Ptr data = rawData.GetSubcontainer(0, tuneInfo.dataFileLen());
        const Formats::Chiptune::Container::Ptr source = Formats::Chiptune::CreateCalculatingCrcContainer(data, 0, data->Size());
        props.SetSource(*source);

        const uint_t fps = tuneInfo.songSpeed() == SidTuneInfo::SPEED_CIA_1A || tuneInfo.clockSpeed() == SidTuneInfo::CLOCK_NTSC ? 60 : 50;
        props.SetFramesFrequency(fps);

        const Information::Ptr info = MakePtr<Information>(GetDuration(params), tune, fps, songIdx);
        return MakePtr<Holder>(tune, info, properties);
      }
      catch (const std::exception&)
      {
        return Holder::Ptr();
      }
    }
Exemple #11
0
 Container::Ptr Decode(const Binary::Container& rawData) const override
 {
   using namespace CompiledSTP;
   if (!Player->Match(rawData))
   {
     return Container::Ptr();
   }
   const Binary::TypedContainer typedData(rawData);
   const std::size_t availSize = rawData.Size();
   const typename Version::RawPlayer& rawPlayer = *typedData.GetField<typename Version::RawPlayer>(0);
   const std::size_t playerSize = rawPlayer.GetSize();
   if (playerSize >= std::min(availSize, CompiledSTP::MAX_PLAYER_SIZE))
   {
     Dbg("Invalid player");
     return Container::Ptr();
   }
   Dbg("Detected player in first %1% bytes", playerSize);
   const std::size_t modDataSize = std::min(CompiledSTP::MAX_MODULE_SIZE, availSize - playerSize);
   const Binary::Container::Ptr modData = rawData.GetSubcontainer(playerSize, modDataSize);
   const Dump metainfo = rawPlayer.GetInfo();
   if (CompiledSTP::IsInfoEmpty(metainfo))
   {
     Dbg("Player has empty metainfo");
     if (const Binary::Container::Ptr originalModule = Formats::Chiptune::SoundTrackerPro::ParseCompiled(*modData, Formats::Chiptune::SoundTrackerPro::GetStubBuilder()))
     {
       const std::size_t originalSize = originalModule->Size();
       return CreateContainer(originalModule, playerSize + originalSize);
     }
   }
   else if (const Binary::Container::Ptr fixedModule = Formats::Chiptune::SoundTrackerPro::InsertMetaInformation(*modData, metainfo))
   {
     if (Formats::Chiptune::SoundTrackerPro::ParseCompiled(*fixedModule, Formats::Chiptune::SoundTrackerPro::GetStubBuilder()))
     {
       const std::size_t originalSize = fixedModule->Size() - metainfo.size();
       return CreateContainer(fixedModule, playerSize + originalSize);
     }
     Dbg("Failed to parse fixed module");
   }
   Dbg("Failed to find module after player");
   return Container::Ptr();
 }
Exemple #12
0
 Formats::Chiptune::Container::Ptr Parse(const Binary::Container& data, Builder& target)
 {
   if (data.Size() < sizeof(RawHeader))
   {
     return Formats::Chiptune::Container::Ptr();
   }
   try
   {
     Format format(data);
     format.ParseMainPart(target);
     format.ParseExtendedPart(target);
     const Binary::Container::Ptr subData = format.GetUsedData();
     const std::size_t fixedStart = offsetof(RawHeader, RAM);
     const std::size_t fixedEnd = sizeof(RawHeader);
     return CreateCalculatingCrcContainer(subData, fixedStart, fixedEnd - fixedStart);
   }
   catch (const std::exception&)
   {
     return Formats::Chiptune::Container::Ptr();
   }
 }
Exemple #13
0
 bool FastCheck(const Binary::Container& rawData)
 {
   if (rawData.Size() <= sizeof(Header))
   {
     return false;
   }
   const Header& header = *static_cast<const Header*>(rawData.Start());
   std::size_t minDataStart = sizeof(header);
   for (uint_t reg = 0; reg != header.Buffers.size(); ++reg)
   {
     const BufferDescription& buf = header.Buffers[reg];
     if (buf.SizeHi != 1 && buf.SizeHi != 4)
     {
       return false;
     }
     const std::size_t dataOffset = buf.GetAbsoluteOffset(reg);
     if (dataOffset < minDataStart)
     {
       return false;
     }
     minDataStart = dataOffset;
   }
   return true;
 }
Exemple #14
0
    Formats::Chiptune::Container::Ptr Parse(const Binary::Container& rawData, Builder& target)
    {
      if (!FastCheck(rawData))
      {
        return Formats::Chiptune::Container::Ptr();
      }

      try
      {
        const std::size_t size = rawData.Size();
        const uint8_t* const begin = static_cast<const uint8_t*>(rawData.Start());
        const uint8_t* const end = begin + size;
        const Header& header = *safe_ptr_cast<const Header*>(begin);
        const uint_t frames = fromLE(header.Duration);
        target.SetFrames(frames);
        std::size_t usedBegin = size;
        std::size_t usedEnd = 0;
        for (uint_t reg = 0; reg != header.Buffers.size(); ++reg)
        {
          target.StartChannel(reg);
          const BufferDescription& buf = header.Buffers[reg];
          const std::size_t offset = buf.GetAbsoluteOffset(reg);
          Require(offset < size);
          Stream stream(buf.SizeHi, begin + offset, end);
          ParseBuffer(frames, stream, target);
          usedBegin = std::min(usedBegin, offset);
          usedEnd = std::max<std::size_t>(usedEnd, stream.GetCursor() - begin);
        }
        const Binary::Container::Ptr subData = rawData.GetSubcontainer(0, usedEnd);
        return CreateCalculatingCrcContainer(subData, usedBegin, usedEnd - usedBegin);
      }
      catch (const std::exception&)
      {
        return Formats::Chiptune::Container::Ptr();
      }
    }
 Binary::TypedContainer CreateContainer(const Binary::Container& rawData)
 {
   return Binary::TypedContainer(rawData, std::min(rawData.Size(), MAX_SIZE));
 }