| 139 | } |
| 140 | |
| 141 | void CPatternCompiler::CompileData(int Track, int Pattern, stChannelID Channel) { |
| 142 | const auto *pSong = modfile_.GetSong(Track); // // // |
| 143 | if (!pSong) |
| 144 | return; |
| 145 | const auto *pInstManager = modfile_.GetInstrumentManager(); |
| 146 | |
| 147 | int EffColumns = pSong->GetEffectColumnCount(Channel); |
| 148 | |
| 149 | // Global init |
| 150 | m_iHash = 0; |
| 151 | m_iDuration = 0; |
| 152 | m_iCurrentDefaultDuration = 0xFF; |
| 153 | |
| 154 | m_vData.clear(); |
| 155 | m_vCompressedData.clear(); |
| 156 | |
| 157 | // Local init |
| 158 | unsigned int iPatternLen = pSong->GetPatternLength(); |
| 159 | unsigned char LastInstrument = MAX_INSTRUMENTS + 1; |
| 160 | unsigned char DPCMInst = 0; |
| 161 | |
| 162 | for (unsigned int i = 0; i < iPatternLen; ++i) { |
| 163 | stChanNote ChanNote = pSong->GetPattern(Channel, Pattern).GetNoteOn(i); // // // |
| 164 | |
| 165 | const note_t Note = ChanNote.Note; |
| 166 | const unsigned char Octave = ChanNote.Octave; |
| 167 | const unsigned char Instrument = FindInstrument(ChanNote.Instrument); |
| 168 | const unsigned char Volume = ChanNote.Vol; |
| 169 | |
| 170 | bool Action = false; |
| 171 | |
| 172 | if (ChanNote.Instrument != MAX_INSTRUMENTS && ChanNote.Instrument != HOLD_INSTRUMENT && (is_note(Note) || Note == note_t::echo)) // // // |
| 173 | if (!IsInstrumentCompatible(Channel.Chip, pInstManager->GetInstrumentType(ChanNote.Instrument))) // // // |
| 174 | Print("Error: Missing or incompatible instrument (on row " + conv::from_uint(i) + |
| 175 | ", channel " + std::string {FTEnv.GetSoundChipService()->GetChannelFullName(Channel)} + ", pattern " + conv::from_uint(Pattern) + ")\n"); |
| 176 | |
| 177 | // Check for delays, must come first |
| 178 | for (int j = 0; j < EffColumns; ++j) { |
| 179 | effect_t Effect = ChanNote.Effects[j].fx; |
| 180 | unsigned char EffParam = ChanNote.Effects[j].param; |
| 181 | if (Effect == effect_t::DELAY && EffParam > 0) { |
| 182 | WriteDuration(); |
| 183 | for (int k = 0; k < EffColumns; ++k) { |
| 184 | // Clear skip and jump commands on delayed rows |
| 185 | if (ChanNote.Effects[k].fx == effect_t::SKIP) { |
| 186 | WriteData(Command(CMD_EFF_SKIP)); |
| 187 | WriteData(ChanNote.Effects[k].param + 1); |
| 188 | ChanNote.Effects[k] = { }; |
| 189 | } |
| 190 | else if (ChanNote.Effects[k].fx == effect_t::JUMP) { |
| 191 | WriteData(Command(CMD_EFF_JUMP)); |
| 192 | WriteData(ChanNote.Effects[k].param + 1); |
| 193 | ChanNote.Effects[k] = { }; |
| 194 | } |
| 195 | } |
| 196 | Action = true; |
| 197 | WriteData(Command(CMD_EFF_DELAY)); |
| 198 | WriteData(EffParam); |
nothing calls this directly
no test coverage detected