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); }
void DecodeBlock(Binary::InputStream& stream, std::size_t srcSize, Dump& dst) { const std::size_t LOOKUP = 1; const uint8_t* const src = stream.ReadData(LOOKUP); const std::size_t used = DecodeBlock(src, srcSize, &dst[0], dst.size()); stream.ReadData(used - LOOKUP); }
void ApplyInsertions(Dump& result) const { if (0 == SizeAddon) { return; } Dump tmp(result.size() + SizeAddon); Dump::const_iterator src = result.begin(); const Dump::const_iterator srcEnd = result.end(); auto dst = tmp.begin(); std::size_t oldOffset = 0; for (const auto& ins : Insertions) { if (const std::size_t toCopy = ins.first - oldOffset) { const Dump::const_iterator nextEnd = src + toCopy; dst = std::copy(src, nextEnd, dst); src = nextEnd; oldOffset += toCopy; } dst = std::copy(ins.second.begin(), ins.second.end(), dst); } std::copy(src, srcEnd, dst); result.swap(tmp); }
bool IsInfoEmpty(const Dump& info) { assert(info.size() == 53); //28 is fixed //25 is title const Dump::const_iterator titleStart = info.begin() + 28; return info.end() == std::find_if(titleStart, info.end(), std::bind2nd(std::greater<Char>(), Char(' '))); }
void AddData(const Dump& registers) override { Devices::AYM::Registers& data = Data->Allocate(); const uint_t availRegs = std::min<uint_t>(registers.size(), Devices::AYM::Registers::ENV + 1); for (uint_t reg = 0, mask = 1; reg != availRegs; ++reg, mask <<= 1) { const uint8_t val = registers[reg]; if (reg != Devices::AYM::Registers::ENV || val != 0xff) { data[static_cast<Devices::AYM::Registers::Index>(reg)] = val; } } }
void OnSector(const Formats::CHS& loc, const uint8_t* rawData, std::size_t rawSize, SectorDataType type, std::size_t targetSize) override { Dump result; switch (type) { case RAW_SECTOR: result.assign(rawData, rawData + rawSize); break; case R2P_SECTOR: DecodeR2P(rawData, rawSize, result); break; case RLE_SECTOR: DecodeRLE(rawData, rawSize, result); break; } Require(result.size() == targetSize); Builder->SetSector(loc, result); }
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(); }
void OverwriteData(std::size_t offset, const Dump& data) override { Require(offset + data.size() <= Source.Size()); Require(Overwrites.insert(BlobsMap::value_type(offset, data)).second); }
void InsertData(std::size_t offset, const Dump& data) override { Require(Insertions.insert(BlobsMap::value_type(offset, data)).second); SizeAddon += data.size(); }