diff --git a/Main/src/KryoFluxDevice.cpp b/Main/src/KryoFluxDevice.cpp index 2b0f32a8..1736c334 100644 --- a/Main/src/KryoFluxDevice.cpp +++ b/Main/src/KryoFluxDevice.cpp @@ -513,6 +513,160 @@ return TRUE; // failure may arise later on when attempting to access the Drive } + DWORD CKryoFluxDevice::TrackToKfw1(CTrackReader tr) const{ + // converts specified Track representation into "KFW" format and returns the length of the representation + union{ + PBYTE pb; + PWORD pw; + PDWORD pdw; + }; + pb=dataBuffer; + // - composing the Histogram of unique flux lengths + static const WORD UNIQUE_FLUXES_COUNT_MAX=10000; + class CHistogram sealed{ + WORD nUniqueFluxes; + struct TUniqueFluxInfo sealed{ + WORD sampleCounter; + WORD orderIndex; + DWORD nOccurences; + } uniqueFluxes[UNIQUE_FLUXES_COUNT_MAX]; + WORD descendingByOccurence[UNIQUE_FLUXES_COUNT_MAX]; // keys (SampleCounters) into UniqueFluxes + CMapWordToPtr sampleCounterToFluxInfo; + public: + inline CHistogram() + // ctor + : nUniqueFluxes(0) { + } + + void Add(WORD sampleCounter){ + // registers a new SampleCounter in this Histogram, eventually moving it "up" in the rank of most occurring SampleCounters + PVOID value; + if (sampleCounterToFluxInfo.Lookup(sampleCounter,value)){ + TUniqueFluxInfo &r=*(TUniqueFluxInfo *)value; + for( r.nOccurences++; r.orderIndex>0; r.orderIndex-- ){ + const WORD moreOccuringSampleCounter=descendingByOccurence[r.orderIndex-1]; + sampleCounterToFluxInfo.Lookup( moreOccuringSampleCounter, value ); + TUniqueFluxInfo &rTmp=*(TUniqueFluxInfo *)value; + if (rTmp.nOccurences>=r.nOccurences) + break; + descendingByOccurence[ rTmp.orderIndex=r.orderIndex ]=moreOccuringSampleCounter; + } + descendingByOccurence[r.orderIndex]=sampleCounter; + }else if (nUniqueFluxesorderIndex; + } + + inline WORD operator[](int i) const{ + return descendingByOccurence[i]; + } + } histogram; + DWORD totalSampleCounter=0; + for( tr.SetCurrentTime(0); tr; ){ + const TLogTime currTime=tr.ReadTime(); + int sampleCounter= TimeToStdSampleCounter(currTime)-totalSampleCounter; // temporary 64-bit precision even on 32-bit machines + if (sampleCounter<=0){ // just to be sure + ASSERT(FALSE); // we shouldn't end up here! + continue; + } + totalSampleCounter+=sampleCounter; + if (sampleCounter>0xffff) + continue; // long fluxes below replaced with sequence of quick fluxes to indicate non-formatted area + histogram.Add(sampleCounter); + } + // - writing Signature + static const BYTE Signature[]={ 'K', 'F', 'W', '\x1' }; + pb=(PBYTE)::memcpy( pb, Signature, sizeof(Signature) )+sizeof(Signature); + // - writing header + struct TUniqueFlux sealed{ + BYTE three; + BYTE index; + Utils::CBigEndianWord sampleCounter; + }; + ASSERT( sizeof(TUniqueFlux)==sizeof(DWORD) ); + static const BYTE Data1[]={ 0xF4, 0x01, 0x00, 0x00, 0x88, 0x13, 0x00, 0x00 }; // TODO: find out the meaning + pb=(PBYTE)::memcpy( pb, Data1, sizeof(Data1) )+sizeof(Data1); + const BYTE nUniqueFluxesUsed=std::min( (WORD)255, histogram.GetUniqueFluxesCount() ); + const DWORD nUsedFluxesTableBytes = *pdw++ = nUniqueFluxesUsed*sizeof(TUniqueFlux)+0x0E; // TODO: find out why 0x0E + DWORD &rnFluxDataBytes=*pdw++; // set below + DWORD &rnTrackDataBytes=*pdw++; // set below + pb=(PBYTE)::ZeroMemory(pb,40)+40; // TODO: are these 40 Bytes reserved and thus always zero? + *pb++=4; // TODO: find out why 4 + *pb++=2; // TODO: find out why 2 + *pb++=0; // TODO: find out why 0 + for( BYTE i=0; i0xffff){ + ASSERT(FALSE); // TODO: replacing long fluxes with quick sequence of short fluxes to indicate non-formatted area + continue; + } + if (((pb-fluxesStart)&0x7fff)!=0x7ffc){ + // normal representation of flux as the index into the table of fluxes + trwFluxes.SetCurrentTime( sampleCounter ); + trwFluxes.TruncateCurrentTime(); + const TLogTime smallerSampleCounter=trwFluxes.GetCurrentTime(); + const TLogTime biggerSampleCounter=trwFluxes.ReadTime(); + if (sampleCounter-smallerSampleCounter