Exemple #1
0
// TODO: subclass from chunk and do processing there?
//
bool CIffIlbm::ParseBitmapHeader(uint8_t *pChunkData, CIffChunk *pChunk)
{
    // BMHD bitmap header chunk:
    // should be first in file (according to spec)
    // and needed by later processing of data

    // make byteswapping where necessary to a copy (keep original)
    //BitMapHeader SwappedHd;

    BitMapHeader *pBmHd = (BitMapHeader*)pChunkData;
    m_BmHeader.w = Swap2(pBmHd->w);
    m_BmHeader.h = Swap2(pBmHd->h);
    m_BmHeader.x = Swap2(pBmHd->x);
    m_BmHeader.y = Swap2(pBmHd->y);
    m_BmHeader.nPlanes = pBmHd->nPlanes;
    m_BmHeader.masking = pBmHd->masking;
    m_BmHeader.compression = pBmHd->compression;
    m_BmHeader.pad1 = pBmHd->pad1; // unused
    m_BmHeader.transparentColor = Swap2(pBmHd->transparentColor);
    m_BmHeader.xAspect = pBmHd->xAspect;
    m_BmHeader.yAspect = pBmHd->yAspect;
    m_BmHeader.pageWidth = Swap2(pBmHd->pageWidth);
    m_BmHeader.pageHeight = Swap2(pBmHd->pageHeight);

    return true;
}
void
Make3OptMove(Node * t1, Node * t2, Node * t3, Node * t4,
             Node * t5, Node * t6, int Case)
{
    switch (Case) {
    case 1:
    case 2:
        Swap2(t1, t2, t3, t6, t5, t4);
        return;
    case 5:
        Swap3(t1, t2, t4, t6, t5, t4, t6, t2, t3);
        return;
    case 6:
        Swap2(t3, t4, t5, t1, t2, t3);
        return;
    default:
        eprintf("Make3OptMove: Internal error");
    }
}
Exemple #3
0
//////////////////
//
// XPK fileformat:
// chunk-based, crunched data in chunks
//
// Chunk format:
// * chunk header
// - 1 byte for chunk type
// - 1 byte for chunk header checksum ?
// - 2 bytes for chunk checksum
// - 2/4 bytes for chunk (compressed) length
// - 2/4 bytes for uncompressed length?
// * chunk data
// - amount of packed data given in chunk header..
//
// Note: chunk header may have different size in different file
// according to flags (if "long" sizes are used for chunks).
//
//
void XpkTags::ReadChunks(CIOBuffer &Buffer)
{
	m_pFirst = new XpkChunk();
	m_pFirst->m_nDataOffset = Buffer.GetCurrentPos();

	XpkChunk *pCurrent = m_pFirst;
	while (Buffer.IsEnd() == false)
	{
		bool isValidHeader = false;
		if (m_streamHeader.xsh_Flags & XPKSTREAMF_LONGHEADERS)
		{
			XpkChunkHdrLong *pHdr = (XpkChunkHdrLong*)Buffer.GetAtCurrent();
			
			pCurrent->m_Type = pHdr->xchl_Type;
			pCurrent->m_HChecksum = pHdr->xchl_HChk;
			pCurrent->m_ChunkChecksum = Swap2(pHdr->xchl_CChk);
			pCurrent->m_ChunkLength = Swap4(pHdr->xchl_CLen);
			pCurrent->m_UnLen = Swap4(pHdr->xchl_ULen);
			
			pCurrent->m_nDataOffset += sizeof(XpkChunkHdrLong);
			isValidHeader = verifyHeaderLong(pHdr);
		}
		else
		{
			XpkChunkHdrWord *pHdr = (XpkChunkHdrWord*)Buffer.GetAtCurrent();
			
			pCurrent->m_Type = pHdr->xchw_Type;
			pCurrent->m_HChecksum = pHdr->xchw_HChk;
			pCurrent->m_ChunkChecksum = Swap2(pHdr->xchw_CChk);
			pCurrent->m_ChunkLength = Swap2(pHdr->xchw_CLen);
			pCurrent->m_UnLen = Swap2(pHdr->xchw_ULen);

			pCurrent->m_nDataOffset += sizeof(XpkChunkHdrWord);
			isValidHeader = verifyHeaderWord(pHdr);
		}
		
		// TODO: need header checksum verification somewhere around here..
		if (isValidHeader == false)
		{
			// TODO: exception or skip ?
		}
		
		if (pCurrent->m_Type != XPKCHUNK_RAW
			&& pCurrent->m_Type != XPKCHUNK_PACKED
			&& pCurrent->m_Type != XPKCHUNK_END)
		{
			// TODO: exception or skip ?
		}
		
		// move to actual data of chunk (according to chunk header size)
		Buffer.SetCurrentPos(pCurrent->m_nDataOffset);

		// "end-of-file" chunk? (empty)
		if (pCurrent->m_Type == XPKCHUNK_END)
		{
			return;
		}
		
		// TODO:
		// .. process chunk
		// -> walkthrough in XPK-master now..
		
		// offset to start of next chunk:
		// start of data in current + size of data in current
		size_t nNextChunkOffset = pCurrent->m_nDataOffset + pCurrent->m_ChunkLength;
		Buffer.SetCurrentPos(nNextChunkOffset);
		
		pCurrent->m_pNext = new XpkChunk(pCurrent);
		pCurrent->m_pNext->m_nDataOffset = nNextChunkOffset;
		pCurrent = pCurrent->m_pNext;
	}
}
Exemple #4
0
void CIffIlbm::OnChunk(CIffChunk *pChunk, CMemoryMappedFile &pFile)
{
    // "raw" data of the chunk,
    // locate by offset
    uint8_t *pChunkData = CIffContainer::GetViewByOffset(pChunk->m_iOffset, pFile);

    // suitable handling for chunk data..
    if (pChunk->m_iChunkID == MakeTag("BMHD"))
    {
        // BMHD bitmap header chunk:
        // should be first in file (according to spec)
        // and needed by later processing of data
        ParseBitmapHeader(pChunkData, pChunk);
    }
    else if (pChunk->m_iChunkID == MakeTag("CMAP"))
    {
        // CMAP color map chunk
        m_lCmapCount = (pChunk->m_iChunkSize/sizeof(ColorRegister));
        m_pCmap = new ColorRegister[m_lCmapCount];

        // bytes only, copy as-is: no need for byteswap
        ::memcpy(m_pCmap, pChunkData, m_lCmapCount*sizeof(ColorRegister));
    }
    else if (pChunk->m_iChunkID == MakeTag("GRAB"))
    {
        // GRAB "hotspot" position (optional)
        // (e.g. brush center)
        Point2D *pPt = (Point2D*)pChunkData;
        m_Pt2d.x = Swap2(pPt->x);
        m_Pt2d.y = Swap2(pPt->y);
    }
    else if (pChunk->m_iChunkID == MakeTag("DEST"))
    {
        // DEST (optional)
        DestMerge *pDst = (DestMerge*)pChunkData;
        m_DestMerge.depth = pDst->depth;
        m_DestMerge.pad1 = pDst->pad1; // padding, not necessary
        m_DestMerge.planePick = Swap2(pDst->planePick);
        m_DestMerge.planeOnOff = Swap2(pDst->planeOnOff);
        m_DestMerge.planeMask = Swap2(pDst->planeMask);
    }
    else if (pChunk->m_iChunkID == MakeTag("CRNG"))
    {
        // CRNG (optional), "nonstandard"
        // used by e.g. EA Deluxe Paint
        CRange *pRange = (CRange*)pChunkData;
        m_Range.pad1 = Swap2(pRange->pad1); // padding, not necessary
        m_Range.rate = Swap2(pRange->rate);
        m_Range.active = Swap2(pRange->active);
        m_Range.low = pRange->low;
        m_Range.high = pRange->high;
    }
    else if (pChunk->m_iChunkID == MakeTag("CCRT"))
    {
        // CCRT (optional)
        // (Color Cycling Range and Timing)
        CycleInfo *pCcrt = (CycleInfo*)pChunkData;
        m_CycleInfo.direction = Swap2(pCcrt->direction);
        m_CycleInfo.start = pCcrt->start;
        m_CycleInfo.end = pCcrt->end;
        m_CycleInfo.seconds = Swap4(pCcrt->seconds);
        m_CycleInfo.microseconds = Swap4(pCcrt->microseconds);
        m_CycleInfo.pad = Swap2(pCcrt->pad); // padding, not necessary
    }
    else if (pChunk->m_iChunkID == MakeTag("SPRT"))
    {
        // SPRT (optional),
        // when image intended as a sprite:
        // "Z"-plane order of sprite (0 foremost)
        m_SpriteOrder = Swap2((*(SpritePrecedence*)pChunkData));
    }
    else if (pChunk->m_iChunkID == MakeTag("CAMG"))
    {
        // CAMG (optional),
        // Amiga "viewport mode"
        // e.g. "dual playfield", "hold and modify"
        m_lViewPortMode = Swap4((*((LONG*)pChunkData)));
    }
    else if (pChunk->m_iChunkID == MakeTag("BODY"))
    {
        // BODY raster body chunk
        // content is concatenation of scan lines

        ParseBody(pChunkData, pChunk);
    }

}
Exemple #5
0
bool COktalyzerPlayer::OnChunk(uint32_t chunkID, const uint32_t chunkLen)
{
    if (chunkID == IFFTag("CMOD"))
    {
        // channel modes
        for (int i = 0; i < 4; i++)
        {
            m_chan_flags[i] = Swap2(m_pFileData->NextUI2());
        }
        return true;
    }
    else if (chunkID == IFFTag("SAMP"))
    {
        // sample directories
        
		// should be 36 samples? (32 bytes each)
        m_nSampleCount = (chunkLen / sizeof(OKTSampleDirectory_t));
        
        // first sample body -> allocate all..
        m_pSamples = new OKTSampleData[m_nSampleCount];
        for (int i = 0; i < m_nSampleCount; i++)
        {
            // byteswap & keep values
            
            OKTSampleDirectory_t *pSampleDir = (OKTSampleDirectory_t*)m_pFileData->GetAtCurrent();
            
            ::memcpy(m_pSamples[i].m_sampleInfo.Sample_Name, pSampleDir->Sample_Name, 20);
            m_pSamples[i].m_sampleInfo.Sample_Len = Swap4(pSampleDir->Sample_Len);
            m_pSamples[i].m_sampleInfo.Repeat_Start = Swap2(pSampleDir->Repeat_Start);
            m_pSamples[i].m_sampleInfo.Repeat_Len = Swap2(pSampleDir->Repeat_Len);
            m_pSamples[i].m_sampleInfo.Volume = pSampleDir->Volume;
            
            m_pFileData->SetCurrentPos(m_pFileData->GetCurrentPos() + sizeof(OKTSampleDirectory_t));
        }
        return true;
    }
    else if (chunkID == IFFTag("SPEE"))
    {
        // speed (initial tempo)
        // Vertical blank divisor for speed/tempo of playback ?
        //
        m_AmigaVBLDivisor = Swap2(m_pFileData->NextUI2());
        return true;
    }
    else if (chunkID == IFFTag("SLEN"))
    {
        // song length: count of patterns in module,
        // use same for number of "PBODY" chunks
        //
        m_SongLength = Swap2(m_pFileData->NextUI2());
        return true;
    }
    else if (chunkID == IFFTag("PLEN"))
    {
        // number of pattern positions (see "PATT" chunk)
        m_NumPatternPositions = Swap2(m_pFileData->NextUI2());
        return true;
    }
    else if (chunkID == IFFTag("PATT"))
    {
        // pattern positions
        // seems to be fixed length chunk?
        // just byte* position
        
        m_PatternPositions.m_nLen = chunkLen;
        m_PatternPositions.m_pBuf = new uint8_t[m_PatternPositions.m_nLen];
        m_pFileData->NextArray(m_PatternPositions.m_pBuf, m_PatternPositions.m_nLen);
        
        return true;
    }
    else if (chunkID == IFFTag("PBOD"))
    {
        // first pattern body -> allocate all..
        if (m_pPatternBody == nullptr)
        {
            m_pPatternBody = new OKTPatternData[m_SongLength];
        }

        // TODO: index next body-chunk
        // or replace with nodelist..?
        size_t n; // current index ?
        
        // pattern body 1..n (multiple in single module),
        // multiple lines (one for each channel?)
        //
        m_pPatternBody[n].num_pattern_lines = Swap2(m_pFileData->NextUI2());
        m_pPatternBody[n].pattern_lines = new OKTPatternLine_t[m_pPatternBody[n].num_pattern_lines];
        
        for (int i = 0; i < m_pPatternBody[n].num_pattern_lines; i++)
        {
            // pattern line
            OKTPatternLine_t *pLine = (OKTPatternLine_t*)m_pFileData->GetAtCurrent();
            
            m_pPatternBody[n].pattern_lines[i].newnote = pLine->newnote;
            m_pPatternBody[n].pattern_lines[i].instrument = pLine->instrument;
            m_pPatternBody[n].pattern_lines[i].effect = pLine->effect;
            m_pPatternBody[n].pattern_lines[i].data = pLine->data;
            
            m_pFileData->SetCurrentPos(m_pFileData->GetCurrentPos() + sizeof(OKTPatternLine_t));
        }
        return true;
    }
    else if (chunkID == IFFTag("SBOD"))
    {
        // sample body 1..n (multiple in single module)
        // use m_nSampleCount counted in "SAMP" ?
        //
        // just byte* sample_data
        
        size_t n; // current index ?
        m_pSamples[n].m_sampleData.m_nLen = chunkLen;
        m_pSamples[n].m_sampleData.m_pBuf = new uint8_t[m_pSamples[n].m_sampleData.m_nLen];
        m_pFileData->NextArray(m_pSamples[n].m_sampleData.m_pBuf, m_pSamples[n].m_sampleData.m_nLen);
        return true;
    }

    // not finished yet..    
    return false;
}
bool CDigiBoosterProPlayer::OnChunk(uint32_t chunkID, const uint32_t chunkLen)
{
    if (chunkID == IFFTag("NAME"))
    {
        // fixed length: 44 characters for module name
        m_moduleName.assign((char*)m_pFileData->GetAtCurrent(), 44);
        return true;
    }
    else if (chunkID == IFFTag("INFO"))
    {
        // module info chunk, fixed size: 10 bytes
        
        DBMInfoChunk_t *pInfo = (DBMInfoChunk_t*)m_pFileData->GetAtCurrent();
        m_moduleInfo.m_instruments = Swap2(pInfo->m_instruments);
        m_moduleInfo.m_samples = Swap2(pInfo->m_samples);
        m_moduleInfo.m_songs = Swap2(pInfo->m_songs);
        m_moduleInfo.m_patterns = Swap2(pInfo->m_patterns);
        m_moduleInfo.m_tracks = Swap2(pInfo->m_tracks);
        return true;
    }
    else if (chunkID == IFFTag("SONG"))
    {
        // songs hunk, variable length
        
        m_pSongBlocks = new DBMSong[m_moduleInfo.m_songs];

        for (int song = 0; song < m_moduleInfo.m_songs; song++)
        {
            // song name
            m_pSongBlocks[song].m_name.assign((char*)m_pFileData->GetAtCurrent(), 44);
            m_pFileData->SetCurrentPos(m_pFileData->GetCurrentPos() + 44);
            
            // song orders
            m_pSongBlocks[song].m_playlistCount = Swap2(m_pFileData->NextUI2());
            m_pSongBlocks[song].m_pOrders = new uint16_t[m_pSongBlocks[song].m_playlistCount];
            for (int i = 0; i < m_pSongBlocks[song].m_playlistCount; i++)
            {
                m_pSongBlocks[song].m_pOrders[i] = Swap2(m_pFileData->NextUI2());
            }
        }
        return true;
    }
    else if (chunkID == IFFTag("INST"))
    {
        // instruments hunk, variable length
        
        m_pInstrBlocks = new DBMInstrument[m_moduleInfo.m_instruments];
        
        for (int instr = 0; instr < m_moduleInfo.m_instruments; instr++)
        {
            // instrument name
            m_pInstrBlocks[instr].m_name.assign((char*)m_pFileData->GetAtCurrent(), 44);
            m_pFileData->SetCurrentPos(m_pFileData->GetCurrentPos() + 44);
            
            DBMInstrumentChunk_t *pInst = (DBMInstrumentChunk_t*)m_pFileData->GetAtCurrent();
            m_pInstrBlocks[instr].m_instruments.m_sampleNumber = Swap2(pInst->m_sampleNumber);
            m_pInstrBlocks[instr].m_instruments.m_volume = Swap2(pInst->m_volume);
            m_pInstrBlocks[instr].m_instruments.m_finetune = Swap4(pInst->m_finetune);
            m_pInstrBlocks[instr].m_instruments.m_repeatStart = Swap4(pInst->m_repeatStart);
            m_pInstrBlocks[instr].m_instruments.m_repeatLength = Swap4(pInst->m_repeatLength);
            m_pInstrBlocks[instr].m_instruments.m_generalPanning = Swap2(pInst->m_generalPanning);
            m_pInstrBlocks[instr].m_instruments.m_flags = Swap2(pInst->m_flags);
        }
        return true;
    }
    else if (chunkID == IFFTag("PATT"))
    {
        // patterns hunk, variable length

        m_pPatternBlocks = new DBMPattern[m_moduleInfo.m_patterns];
        
        for (int patt = 0; patt < m_moduleInfo.m_patterns; patt++)
        {
            m_pPatternBlocks[patt].m_rowCount = Swap2(m_pFileData->NextUI2());
            
            // packed pattern: size and data
            m_pPatternBlocks[patt].m_patternData.m_nLen = Swap2(m_pFileData->NextUI2());
            m_pPatternBlocks[patt].m_patternData.m_pBuf = new uint8_t[m_pPatternBlocks[patt].m_patternData.m_nLen];
            
            // copy packed pattern data
            m_pFileData->NextArray(m_pPatternBlocks[patt].m_patternData.m_pBuf, m_pPatternBlocks[patt].m_patternData.m_nLen);
            
            // TODO: unpacking while playing?
        }
        return true;
    }
    else if (chunkID == IFFTag("SMPL"))
    {
        // samples hunk, variable length
        // note: sample data actually signed integers, take note on playback
        
        m_pSampleBlocks = new DBMSample[m_moduleInfo.m_samples];
        for (int smpl = 0; smpl < m_moduleInfo.m_samples; smpl++)
        {
            // flags:
            // - bit 0 set - 8 bit sample
            // - bit 1 set - 16 bit sample
            // - bit 2 set - 32 bit sample
            //
            m_pSampleBlocks[smpl].m_flags = Swap4(m_pFileData->NextUI4());
            
            // sample data: size and data
            m_pSampleBlocks[smpl].m_sampleData.m_nLen = Swap4(m_pFileData->NextUI4());
            m_pSampleBlocks[smpl].m_sampleData.m_pBuf = new uint8_t[m_pSampleBlocks[smpl].m_sampleData.m_nLen];
            ::memcpy(m_pSampleBlocks[smpl].m_sampleData.m_pBuf, m_pFileData->GetAtCurrent(), m_pSampleBlocks[smpl].m_sampleData.m_nLen);
    
            // - check flag for sample size
            // - swap byteorder for each value in buffer
            //
            uint32_t flag = 1;
            if (m_pSampleBlocks[smpl].m_flags & (flag << 1))
            {
                // 16-bit
                uint16_t *pBuf = (uint16_t*)m_pSampleBlocks[smpl].m_sampleData.m_pBuf;
                int count = m_pSampleBlocks[smpl].m_sampleData.m_nLen / sizeof(uint16_t);
                for (int i = 0; i < count; i++)
                {
                    pBuf[i] = Swap2(pBuf[i]);
                }
            }
            else if (m_pSampleBlocks[smpl].m_flags & (flag << 2))
            {
                // 32-bit
                uint32_t *pBuf = (uint32_t*)m_pSampleBlocks[smpl].m_sampleData.m_pBuf;
                int count = m_pSampleBlocks[smpl].m_sampleData.m_nLen / sizeof(uint32_t);
                for (int i = 0; i < count; i++)
                {
                    pBuf[i] = Swap4(pBuf[i]);
                }
            }
        }
        return true;
    }
    else if (chunkID == IFFTag("VENV"))
    {
        // volume envelopes hunk (optional), variable length,
        // contains n amount of fixed-size blocks
        
        m_volEnvelopeCount = Swap2(m_pFileData->NextUI2());
        
        m_pVolEnvelopes = new DBMEnvelope[m_volEnvelopeCount];
        for (int env = 0; env < m_volEnvelopeCount; env++)
        {
            // volume envelope is fixed size 
            
            DBMEnvelope_t *pVEnv = (DBMEnvelope_t*)m_pFileData->GetAtCurrent();
            ::memcpy(&(m_pVolEnvelopes[env].m_envelope), pVEnv, sizeof(DBMEnvelope_t));
            
            m_pVolEnvelopes[env].m_envelope.m_instrumentNumber = Swap2(m_pVolEnvelopes[env].m_envelope.m_instrumentNumber);
            m_pFileData->SetCurrentPos(m_pFileData->GetCurrentPos() + sizeof(DBMEnvelope_t));
            
            // rest of data..
            m_pVolEnvelopes[env].m_envelopeData.m_nLen = (136 - sizeof(DBMEnvelope_t));
            m_pVolEnvelopes[env].m_envelopeData.m_pBuf = new uint8_t[m_pVolEnvelopes[env].m_envelopeData.m_nLen];
            m_pFileData->NextArray(m_pVolEnvelopes[env].m_envelopeData.m_pBuf, m_pVolEnvelopes[env].m_envelopeData.m_nLen);

            // for simplicity.. do some parsing&byteswapping for later use
            uint16_t *pEnvPts = (uint16_t*)(m_pVolEnvelopes[env].m_envelopeData.m_pBuf);
            int count = (m_pVolEnvelopes[env].m_envelopeData.m_nLen / sizeof(uint16_t));
            for (int i = 0; i < count; i++)
            {
                pEnvPts[i] = Swap2(pEnvPts[i]);
            }
        }
        return true;
    }
    else if (chunkID == IFFTag("PENV"))
    {
        // panning envelopes hunk (optional), variable length,
        // contains n amount of fixed-size blocks
        
        m_panEnvelopeCount = Swap2(m_pFileData->NextUI2());
        
        m_pPanEnvelopes = new DBMEnvelope[m_panEnvelopeCount];
        for (int env = 0; env < m_panEnvelopeCount; env++)
        {
            // volume envelope is fixed size 
            
            DBMEnvelope_t *pPEnv = (DBMEnvelope_t*)m_pFileData->GetAtCurrent();
            ::memcpy(&(m_pPanEnvelopes[env].m_envelope), pPEnv, sizeof(DBMEnvelope_t));
            
            m_pPanEnvelopes[env].m_envelope.m_instrumentNumber = Swap2(m_pPanEnvelopes[env].m_envelope.m_instrumentNumber);
            m_pFileData->SetCurrentPos(m_pFileData->GetCurrentPos() + sizeof(DBMEnvelope_t));
            
            // rest of data..
            m_pPanEnvelopes[env].m_envelopeData.m_nLen = (136 - sizeof(DBMEnvelope_t));
            m_pPanEnvelopes[env].m_envelopeData.m_pBuf = new uint8_t[m_pPanEnvelopes[env].m_envelopeData.m_nLen];
            m_pFileData->NextArray(m_pPanEnvelopes[env].m_envelopeData.m_pBuf, m_pPanEnvelopes[env].m_envelopeData.m_nLen);

            // for simplicity.. do some parsing&byteswapping for later use
            uint16_t *pEnvPts = (uint16_t*)(m_pPanEnvelopes[env].m_envelopeData.m_pBuf);
            int count = (m_pPanEnvelopes[env].m_envelopeData.m_nLen / sizeof(uint16_t));
            for (int i = 0; i < count; i++)
            {
                pEnvPts[i] = Swap2(pEnvPts[i]);
            }
        }
        return true;
    }
    else if (chunkID == IFFTag("PNAM"))
    {
        // pattern names (optional?), variable length
        // chunk added in newer Digibooster 3?

        // encoding used in names:
        // 0    = 8-bit ASCII
        // 106  = UTF-8
        //
        m_patternNameEncoding = Swap2(m_pFileData->NextUI2());

        // TODO: get QTextCodec for codepage conversion..
        
        m_pPatternNames = new std::string[m_moduleInfo.m_patterns];
        for (int i = 0; i < m_moduleInfo.m_patterns; i++)
        {
            uint8_t len = m_pFileData->NextUI1();
            m_pPatternNames[i].assign((char*)m_pFileData->GetAtCurrent(), len);
            m_pFileData->SetCurrentPos(m_pFileData->GetCurrentPos() + len);
        }
        return true;
    }
    
    // TODO: debug output: unsupport chunk found..
    return false;
}