// 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"); } }
////////////////// // // 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; } }
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); } }
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; }