Example #1
0
    bool FastCheck() const
    {
      if (Size <= sizeof(RawHeader))
      {
        return false;
      }
      const RawHeader& header = GetHeader();
      const uint_t endOfBlock = fromLE(header.LastSrcRestBytes) + 1;
      const uint_t lastBytesAddr = endOfBlock - LAST_BYTES_COUNT;
      const uint_t bitStreamAddr = lastBytesAddr - fromLE(header.SizeOfPacked);

      const uint_t srcPacked = fromLE(header.SrcPacked);
      if (bitStreamAddr == srcPacked)
      {
        //move forward
      }
      else if (lastBytesAddr == srcPacked + 1)
      {
        //move backward
      }
      else
      {
        return false;
      }
      const std::size_t usedSize = GetUsedSize();
      return Math::InRange(usedSize, sizeof(header), Size);
    }
Example #2
0
 ModuleTraits(const Binary::Data& data, std::size_t footerOffset)
   : FooterOffset(footerOffset)
   , Foot(footerOffset != data.Size() ? safe_ptr_cast<const Footer*>(static_cast<const uint8_t*>(data.Start()) + footerOffset) : 0)
   , FirstSize(Foot ? fromLE(Foot->Size1) : 0)
   , SecondSize(Foot ? fromLE(Foot->Size2) : 0)
 {
 }
Example #3
0
    void GetResult(Dump& data) const override
    {
      Dump rawDump;
      Delegate->GetResult(rawDump);
      Require(0 == rawDump.size() % Registers::TOTAL);
      const uint32_t framesCount = rawDump.size() / Registers::TOTAL;
      const uint_t storedRegisters = Registers::TOTAL;

      const String& title = Params->Title();
      const String author = Params->Author();
      const uint32_t headerSize = sizeof(FYMHeader) + (title.size() + 1) + (author.size() + 1);
      const std::size_t contentSize = framesCount * storedRegisters;

      Binary::DataBuilder builder(headerSize + contentSize);
      FYMHeader& header = builder.Add<FYMHeader>();
      header.HeaderSize = fromLE(headerSize);
      header.FramesCount = fromLE(framesCount);
      header.LoopFrame = fromLE(static_cast<uint32_t>(Params->LoopFrame()));
      header.PSGFreq = fromLE(static_cast<uint32_t>(Params->ClockFreq()));
      header.IntFreq = fromLE(static_cast<uint32_t>(Time::GetFrequencyForPeriod(Params->FrameDuration())));
      builder.AddCString(title);
      builder.AddCString(author);

      for (uint_t reg = 0; reg < storedRegisters; ++reg)
      {
        uint8_t* const result = static_cast<uint8_t*>(builder.Allocate(framesCount));
        for (uint_t frm = 0, inOffset = reg; frm < framesCount; ++frm, inOffset += Registers::TOTAL)
        {
          result[frm] = rawDump[inOffset];
        }
      }
      Dump result;
      builder.CaptureResult(result);
      Binary::Compression::Zlib::Compress(result, data);
    }
Example #4
0
 static void Fix(void* data, int_t delta)
 {
   T* const ptr = static_cast<T*>(data);
   const T val = fromLE(*ptr);
   const T fixedVal = static_cast<T>(val + delta);
   *ptr = fromLE(fixedVal);
 }
Example #5
0
 bool FastCheck() const
 {
   if (Size < sizeof(RawHeader))
   {
     return false;
   }
   const RawHeader& header = GetHeader();
   BOOST_STATIC_ASSERT(sizeof(header.ID) == sizeof(FDI_ID));
   if (0 != std::memcmp(header.ID, FDI_ID, sizeof(FDI_ID)))
   {
     return false;
   }
   const std::size_t dataOffset = fromLE(header.DataOffset);
   if (dataOffset < sizeof(header) ||
       dataOffset > Size)
   {
     return false;
   }
   const uint_t cylinders = fromLE(header.Cylinders);
   if (!Math::InRange(cylinders, MIN_CYLINDERS_COUNT, MAX_CYLINDERS_COUNT))
   {
     return false;
   }
   const uint_t sides = fromLE(header.Sides);
   if (!Math::InRange(sides, MIN_SIDES_COUNT, MAX_SIDES_COUNT))
   {
     return false;
   }
   return true;
 }
 void ParseROM(Builder& target)
 {
   while (const auto size = fromLE(Stream.ReadField<uint32_t>()))
   {
     const auto offset = fromLE(Stream.ReadField<uint32_t>());
     target.SetRom(offset, *Stream.ReadData(size));
   }
 }
 void ParseRegisters(Builder& target)
 {
   Stream.Seek(0x10);
   const auto pc = fromLE(Stream.ReadField<uint32_t>());
   const auto gp = fromLE(Stream.ReadField<uint32_t>());
   Dbg("PC=0x%08x GP=0x%08x", pc, gp);
   target.SetRegisters(pc, gp);
 }
 void ParseStackSection(Builder& target)
 {
   Stream.Seek(0x30);
   const auto stackHead = fromLE(Stream.ReadField<uint32_t>());
   const auto stackSize = fromLE(Stream.ReadField<uint32_t>());
   Dbg("Stack %u bytes at 0x%08x", stackSize, stackHead);
   target.SetStackRegion(stackHead, stackSize);
 }
Example #9
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;
   }
 }
Example #10
0
 void ParsePositions(Builder& builder) const
 {
   std::vector<PositionEntry> positions;
   uint_t loop = 0;
   PositionEntry entry;
   for (std::size_t posCursor = fromLE(Source.PositionsOffset); ; ++posCursor)
   {
     Require(positions.size() <= MAX_POSITIONS_COUNT);
     const uint_t val = PeekByte(posCursor);
     if (val == 0xff)
     {
       break;
     }
     else if (val == 0xfe)
     {
       loop = positions.size();
     }
     else if (val >= 0x60)
     {
       entry.Transposition = val - 0x60;
     }
     else
     {
       Require(0 == val % 3);
       entry.PatternIndex = val / 3;
       positions.push_back(entry);
     }
   }
   Require(!positions.empty());
   builder.SetPositions(positions, loop);
   Dbg("Positions: %1% entries, loop to %2%", positions.size(), loop);
 }
Example #11
0
 void ParseSectors(SourceStream& stream, ImageVisitor& visitor)
 {
   for (;;)
   {
     const RawTrack& track = stream.Get<RawTrack>();
     if (track.IsLast())
     {
       break;
     }
     Require(Math::InRange<uint_t>(track.Cylinder, 0, MAX_CYLINDERS_COUNT));
     for (uint_t sect = 0; sect != track.Sectors; ++sect)
     {
       const RawSector& sector = stream.Get<RawSector>();
       if (sector.NoData())
       {
         continue;
       }
       Require(Math::InRange<uint_t>(sector.Size, 0, 6));
       const std::size_t sectorSize = std::size_t(128) << sector.Size;
       const RawData& srcDataDesc = stream.Get<RawData>();
       Require(Math::InRange<uint_t>(srcDataDesc.Method, RAW_SECTOR, RLE_SECTOR));
       const std::size_t dataSize = fromLE(srcDataDesc.Size) - 1;
       const uint8_t* const rawData = stream.GetData(dataSize);
       //use track parameters for layout
       if (!sector.NoId())
       {
         const Formats::CHS loc(sector.Cylinder, track.Head, sector.Number);
         visitor.OnSector(loc, rawData, dataSize, static_cast<SectorDataType>(srcDataDesc.Method), sectorSize);
       }
     }
   }
 }
Example #12
0
 uint_t GetInteger() const
 {
   if (Type == Length)
   {
     return fromLE(DataSize);
   }
   else if (Type == Integer)
   {
     return fromLE(*safe_ptr_cast<const uint32_t*>(this + 1));
   }
   else
   {
     assert(!"Invalid subchunk type");
     return 0;
   }
 }
 void ParseTextSection(Builder& target)
 {
   Stream.Seek(0x18);
   const auto startAddress = fromLE(Stream.ReadField<uint32_t>());
   const std::size_t size = fromLE(Stream.ReadField<uint32_t>());
   Dbg("Text section %u (%u in header) bytes at 0x%08x", Stream.GetRestSize(), size, startAddress);
   if (size)
   {
     Stream.Seek(HEADER_SIZE);
     target.SetTextSection(startAddress, *Stream.ReadRestData());
   }
   else
   {
     static const Binary::DataAdapter EMPTY(nullptr, 0);
     target.SetTextSection(startAddress, EMPTY);
   }
 }
Example #14
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();
 }
 void ParseSavestate(Builder& target)
 {
   while (const auto size = fromLE(Stream.ReadField<uint32_t>()))
   {
     const auto offset = fromLE(Stream.ReadField<uint32_t>());
     target.SetSaveState(offset, *Stream.ReadData(size));
   }
   /*
   const auto offset = Stream.GetPosition();
   Require(SAVESTATE_SIGNATURE == Stream.ReadField<SignatureType>());
   const auto rdramSize = fromLE(Stream.ReadField<uint32_t>());
   const auto romHeader = Stream.ReadData(0x40);
   Stream.Seek(offset);
   target.SetSaveState(*Stream.ReadData(0x175c + rdramSize));
   target.SetRom(0, *romHeader);
   */
 }
Example #16
0
 Formats::Packed::Container::Ptr DecodeNew(Binary::InputStream& stream)
 {
   const std::size_t ZX_PAGE_SIZE = 16384;
   const Version2_0::Header hdr = stream.ReadField<Version2_0::Header>();
   const std::size_t additionalSize = fromLE(hdr.AdditionalSize);
   const std::size_t readAdditionalSize = sizeof(hdr) - sizeof(Version1_45::Header) - sizeof(hdr.AdditionalSize);
   Require(additionalSize >= readAdditionalSize);
   stream.ReadData(additionalSize - readAdditionalSize);
   const PlatformTraits traits(additionalSize, hdr.HardwareMode, hdr.Port7ffd);
   std::auto_ptr<Dump> res(new Dump(ZX_PAGE_SIZE * traits.PagesCount()));
   Dump curPage(ZX_PAGE_SIZE);
   for (uint_t idx = 0; idx != traits.PagesCount(); ++idx)
   {
     const bool isPageRequired = idx < traits.MinimalPagesCount();
     if (!isPageRequired && stream.GetRestSize() < sizeof(Version2_0::MemoryPage))
     {
       break;
     }
     const Version2_0::MemoryPage page = stream.ReadField<Version2_0::MemoryPage>();
     const int_t pageNumber = traits.PageNumber(page.Number);
     const bool isPageValid = pageNumber != PlatformTraits::NO_PAGE;
     if (!isPageRequired && !isPageValid)
     {
       break;
     }
     Require(isPageValid);
     const std::size_t pageSize = fromLE(page.DataSize);
     const uint8_t* pageSource = 0;
     if (pageSize == page.UNCOMPRESSED)
     {
       pageSource = stream.ReadData(ZX_PAGE_SIZE);
     }
     else
     {
       Require(pageSize <= stream.GetRestSize());
       DecodeBlock(stream, pageSize, curPage);
       pageSource = &curPage.front();
     }
     std::memcpy(&res->front() + pageNumber * ZX_PAGE_SIZE, pageSource, ZX_PAGE_SIZE);
   }
   return CreatePackedContainer(res, stream.GetPosition());
 }
Example #17
0
 bool FastCheck() const
 {
   if (Size < sizeof(typename Version::RawHeader))
   {
     return false;
   }
   const typename Version::RawHeader& header = GetHeader();
   const DataMovementChecker checker(fromLE(header.PackedDataSrc), 
     fromLE(header.PackedDataDst), fromLE(header.PackedDataSize), header.PackedDataCopyDirection);
   if (!checker.IsValid())
   {
     return false;
   }
   const uint_t usedSize = GetUsedSize();
   if (usedSize > Size)
   {
     return false;
   }
   return true;
 }
Example #18
0
 bool DecodeData()
 {
   // The main concern is to decode data as much as possible, skipping defenitely invalid structure
   Decoded.reserve(2 * fromLE(Header.SizeOfPacked));
   //assume that first byte always exists due to header format
   while (!Stream.Eof() && Decoded.size() < MAX_DECODED_SIZE)
   {
     const uint_t data = Stream.GetByte();
     if (0x80 == data)
     {
       //exit
       break;
     }
     //at least one more byte required
     if (Stream.Eof())
     {
       return false;
     }
     const uint_t code = data & 0xc0;
     if (0x80 == code)
     {
       uint_t len = data & 0x3f;
       assert(len);
       for (; len && !Stream.Eof(); --len)
       {
         Decoded.push_back(Stream.GetByte());
       }
       if (len)
       {
         return false;
       }
     }
     else if (0xc0 == code)
     {
       const std::size_t len = (data & 0x3f) + 3;
       const uint8_t data = Stream.GetByte();
       std::fill_n(std::back_inserter(Decoded), len, data);
     }
     else
     {
       const std::size_t len = ((data & 0xf0) >> 4) + 3;
       const uint_t offset = 256 * (data & 0x0f) + Stream.GetByte();
       if (!CopyFromBack(offset, Decoded, len))
       {
         return false;
       }
     }
   }
   while (!Stream.Eof())
   {
     Decoded.push_back(Stream.GetByte());
   }
   return true;
 }
Example #19
0
 explicit DataDecoder(const Container& container)
   : IsValid(container.FastCheck())
   , Header(container.GetHeader())
   , Stream(Header.BitStream, fromLE(Header.SizeOfPacked))
   , Result(new Dump())
   , Decoded(*Result)
 {
   if (IsValid && !Stream.Eof())
   {
     IsValid = DecodeData();
   }
 }
Example #20
0
    bool DecodeData()
    {
      const uint8_t* const rawData = static_cast<const uint8_t*>(Header.ID);
      const std::size_t dataOffset = fromLE(Header.DataOffset);
      const uint_t cylinders = fromLE(Header.Cylinders);
      const uint_t sides = fromLE(Header.Sides);

      Dump result;
      result.reserve(FDI_MAX_SIZE);
      std::size_t trackInfoOffset = sizeof(Header) + fromLE(Header.InfoSize);
      std::size_t rawSize = dataOffset;
      for (uint_t cyl = 0; cyl != cylinders; ++cyl)
      {
        for (uint_t sid = 0; sid != sides; ++sid)
        {
          if (trackInfoOffset + sizeof(RawTrack) > Limit)
          {
            return false;
          }

          const RawTrack* const trackInfo = safe_ptr_cast<const RawTrack*>(rawData + trackInfoOffset);
          typedef std::vector<SectorDescr> SectorDescrs;
          //collect sectors reference
          SectorDescrs sectors;
          sectors.reserve(trackInfo->SectorsCount);
          for (std::size_t secNum = 0; secNum != trackInfo->SectorsCount; ++secNum)
          {
            const RawTrack::Sector* const sector = trackInfo->Sectors + secNum;
            const std::size_t secSize = 128 << sector->Size;
            //since there's no information about head number (always 0), do not check it
            //assert(sector->Head == sid);
            if (sector->Cylinder != cyl)
            {
              return false;
            }
            const std::size_t offset = dataOffset + fromLE(sector->Offset) + fromLE(trackInfo->Offset);
            if (offset + secSize > Limit)
            {
              return false;
            }
            sectors.push_back(SectorDescr(sector->Number, rawData + offset, rawData + offset + secSize));
            rawSize = std::max(rawSize, offset + secSize);
          }

          //sort by number
          std::sort(sectors.begin(), sectors.end());
          //and gather data
          for (SectorDescrs::const_iterator it = sectors.begin(), lim = sectors.end(); it != lim; ++it)
          {
            result.insert(result.end(), it->Begin, it->End);
          }
          //calculate next track by offset
          trackInfoOffset += sizeof(*trackInfo) + (trackInfo->SectorsCount - 1) * sizeof(trackInfo->Sectors);
        }
      }
      UsedSize = rawSize;
      Decoded.swap(result);
      return true;
    }
Example #21
0
 void ParseSamples(const Indices& samples, Builder& builder) const
 {
   Dbg("Samples: %1% to parse", samples.Count());
   const std::size_t samplesTable = fromLE(Source.SamplesOffset);
   for (Indices::Iterator it = samples.Items(); it; ++it)
   {
     const uint_t samIdx = *it;
     Dbg("Parse sample %1%", samIdx);
     const std::size_t samOffset = ReadWord(samplesTable, samIdx);
     Sample result;
     ParseSample(samOffset, result);
     builder.SetSample(samIdx, result);
   }
 }
Example #22
0
 void ParseMainPart(Builder& target)
 {
   const RawHeader& hdr = Stream.ReadField<RawHeader>();
   Require(hdr.Signature == SIGNATURE);
   ParseID666(hdr.ID666, target);
   target.SetRegisters(fromLE(hdr.Regs.PC), hdr.Regs.A, hdr.Regs.X, hdr.Regs.Y, hdr.Regs.PSW, hdr.Regs.SP);
   target.SetRAM(hdr.RAM, sizeof(hdr.RAM));
   target.SetDSPRegisters(hdr.DSPRegisters, sizeof(hdr.DSPRegisters));
   if (Stream.GetRestSize() >= sizeof(ExtraRAM))
   {
     const ExtraRAM& extra = Stream.ReadField<ExtraRAM>();
     target.SetExtraRAM(extra.Data, sizeof(extra.Data));
   }
 }
Example #23
0
 void ParseOrnaments(const Indices& ornaments, Builder& builder) const
 {
   Dbg("Ornaments: %1% to parse", ornaments.Count());
   const std::size_t ornamentsTable = fromLE(Source.OrnamentsOffset);
   for (Indices::Iterator it = ornaments.Items(); it; ++it)
   {
     const uint_t ornIdx = *it;
     Dbg("Parse ornament %1%", ornIdx);
     const std::size_t ornOffset = ReadWord(ornamentsTable, ornIdx);
     Ornament result;
     ParseOrnament(ornOffset, result);
     builder.SetOrnament(ornIdx, result);
   }
 }
Example #24
0
 String GetString() const
 {
   if (Type == Asciiz)
   {
     const char* const start = safe_ptr_cast<const char*>(this + 1);
     const char* const end = start + fromLE(DataSize);
     const StringView val = end[-1] ? StringView(start, end) : StringView(start);
     return Strings::OptimizeAscii(val);
   }
   else
   {
     //assert(!"Invalid subchunk type");
     return String();
   }
 }
Example #25
0
 void DecodeR2P(const uint8_t* data, std::size_t size, Dump& result)
 {
   Require(size % sizeof(R2PEntry) == 0);
   Dump tmp;
   tmp.reserve(MAX_SECTOR_SIZE);
   for (const R2PEntry* it = safe_ptr_cast<const R2PEntry*>(data), *lim = it + size / sizeof(*it); it != lim; ++it)
   {
     const uint_t count = fromLE(it->Count);
     Require(count != 0);
     tmp.push_back(it->Data[0]);
     tmp.push_back(it->Data[1]);
     Require(CopyFromBack(sizeof(it->Data), tmp, sizeof(it->Data) * (count - 1)));
   }
   result.swap(tmp);
 }
Example #26
0
 Formats::Packed::Container::Ptr Version1_45::Decode(Binary::InputStream& stream)
 {
   const Version1_45::Header hdr = stream.ReadField<Version1_45::Header>();
   const std::size_t restSize = stream.GetRestSize();
   const std::size_t TARGET_SIZE = 49152;
   const uint32_t FOOTER = 0x00eded00;
   if (0 == (hdr.Flag1 & hdr.COMPRESSED))
   {
     Require(restSize >= TARGET_SIZE);
     const Binary::Container::Ptr rest = stream.ReadRestData();
     return CreatePackedContainer(rest->GetSubcontainer(0, TARGET_SIZE), sizeof(hdr) + TARGET_SIZE);
   }
   Require(restSize > sizeof(FOOTER));
   std::auto_ptr<Dump> res(new Dump(TARGET_SIZE));
   DecodeBlock(stream, restSize - sizeof(FOOTER), *res);
   const uint32_t footer = fromLE(stream.ReadField<uint32_t>());
   Require(footer == FOOTER);
   return CreatePackedContainer(res, stream.GetPosition());
 }
Example #27
0
 void ParseExtendedPart(Builder& target)
 {
   if (Stream.GetPosition() == sizeof(RawHeader) + sizeof(ExtraRAM)
    && Stream.GetRestSize() >= sizeof(IFFChunkHeader))
   {
     const IFFChunkHeader& hdr = Stream.ReadField<IFFChunkHeader>();
     const std::size_t size = fromLE(hdr.DataSize);
     if (hdr.ID == XID6 && Stream.GetRestSize() >= size)
     {
       const auto chunks = Stream.ReadData(size);
       ParseSubchunks(*chunks, target);
     }
     else
     {
       Dbg("Invalid IFFF chunk stored (id=%s, size=%u)", String(hdr.ID.begin(), hdr.ID.end()), size);
       //TODO: fix used size instead
       Stream.ReadRestData();
     }
   }
 }
Example #28
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();
      }
    }
Example #29
0
 std::size_t GetAbsoluteOffset(uint_t idx) const
 {
   return fromLE(Offset) + idx * sizeof(*this) + 4;
 }
Example #30
0
 static void ParseSubchunks(const Binary::Data& data, Builder& target)
 {
   try
   {
     Binary::TypedContainer typed(data);
     for (std::size_t pos = 0; pos < typed.GetSize(); )
     {
       const SubChunkHeader* const hdr = typed.GetField<SubChunkHeader>(pos);
       Require(hdr != nullptr);
       if (hdr->ID == 0 && 0 != (pos % 4))
       {
         //in despite of official format description, subchunks can be not aligned by 4 byte boundary
         ++pos;
       }
       else
       {
         Dbg("ParseSubchunk id=%u, type=%u, size=%u", uint_t(hdr->ID), uint_t(hdr->Type), fromLE(hdr->DataSize));
         pos += sizeof(*hdr) + hdr->GetDataSize();
         Require(pos <= typed.GetSize());
         ParseSubchunk(*hdr, target);
       }
     }
   }
   catch (const std::exception&)
   {
     //ignore
   }
 }