ScanDataContainer(Binary::Container::Ptr delegate, std::size_t offset) : Delegate(delegate) , OriginalSize(delegate->Size()) , OriginalData(static_cast<const uint8_t*>(delegate->Start())) , Offset(offset) { }
DataLocation::Ptr Open(const Parameters::Accessor& /*params*/, DataLocation::Ptr location, const Analysis::Path& inPath) const override { const String& pathComp = inPath.GetIterator()->Get(); std::size_t offset = 0; if (RawPath.GetIndex(pathComp, offset)) { const Binary::Container::Ptr inData = location->GetData(); const Binary::Container::Ptr subData = inData->GetSubcontainer(offset, inData->Size() - offset); return CreateNestedLocation(location, subData, Description->Id(), pathComp); } return DataLocation::Ptr(); }
Analysis::Result::Ptr Detect(const Parameters::Accessor& params, DataLocation::Ptr input, const Module::DetectCallback& callback) const override { const Binary::Container::Ptr rawData = input->GetData(); const std::size_t size = rawData->Size(); Statistic::Self().Enqueue(size); if (size < MIN_MINIMAL_RAW_SIZE) { Dbg("Size is too small (%1%)", size); return Analysis::CreateUnmatchedResult(size); } const RawPluginParameters scanParams(params); const std::size_t minRawSize = scanParams.GetMinimalSize(); const String currentPath = input->GetPath()->AsString(); Dbg("Detecting modules in raw data at '%1%'", currentPath); const Log::ProgressCallback::Ptr progress = MakePtr<RawProgressCallback>(callback, static_cast<uint_t>(size), currentPath); const Module::DetectCallback& noProgressCallback = Module::CustomProgressDetectCallbackAdapter(callback); const ArchivePlugin::Iterator::Ptr availableArchives = ArchivePluginsEnumerator::Create()->Enumerate(); const ArchivePlugin::Iterator::Ptr usedArchives = scanParams.GetDoubleAnalysis() ? MakePtr<DoubleAnalysisArchivePlugins>(availableArchives) : availableArchives; RawDetectionPlugins usedPlugins(params, PlayerPluginsEnumerator::Create()->Enumerate(), usedArchives, *this); ScanDataLocation::Ptr subLocation = MakePtr<ScanDataLocation>(input, Description->Id(), 0); while (subLocation->HasToScan(minRawSize)) { const std::size_t offset = subLocation->GetOffset(); progress->OnProgress(static_cast<uint_t>(offset)); usedPlugins.SetOffset(offset); const Module::DetectCallback& curCallback = offset ? noProgressCallback : callback; const std::size_t bytesToSkip = usedPlugins.Detect(subLocation, curCallback); if (!subLocation.unique()) { Dbg("Sublocation is captured. Duplicate."); subLocation = MakePtr<ScanDataLocation>(input, Description->Id(), offset); } subLocation->Move(std::max(bytesToSkip, SCAN_STEP)); } return Analysis::CreateMatchedResult(size); }
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(); } }