static inline size_t snprint_pointer(char *buf, size_t size, void *ptr, bool left, char padding, size_t width) { char str[35] = "0x"; size_t len = utoa_s((unsigned int)ptr, 16, str + 2, sizeof(str) - 2); if (len == 0) return 0; len += 2; return copy_with_padding(buf, size, str, len, left, padding, width); }
static inline size_t snprint_uint(char *buf, size_t size, unsigned int i, unsigned int base, bool left, char padding, size_t width) { char str[33]; size_t len = utoa_s(i, base, str, sizeof(str)); if (len == 0) return 0; return copy_with_padding(buf, size, str, len, left, padding, width); }
bool module_renderer::SaveITProject(LPCSTR lpszFileName) //------------------------------------------------- { // Check song type if(!(m_dwSongFlags & SONG_ITPROJECT)) return false; UINT i,j = 0; for(i = 0 ; i < m_nInstruments ; i++) { if(m_szInstrumentPath[i][0] != '\0' || !Instruments[i+1]) j++; } if(m_nInstruments && j != m_nInstruments) return false; // Open file FILE *f; if((!lpszFileName) || ((f = fopen(lpszFileName, "wb")) == NULL)) return false; // File ID uint32_t id = ITP_FILE_ID; fwrite(&id, 1, sizeof(id), f); id = ITP_VERSION; fwrite(&id, 1, sizeof(id), f); // Song name // name string length id = 27; fwrite(&id, 1, sizeof(id), f); // song name char namebuf[27]; copy_with_padding(namebuf, 27, this->song_name); fwrite(namebuf, 1, 27, f); // Song comments // comment string length id = m_lpszSongComments ? strlen(m_lpszSongComments)+1 : 0; fwrite(&id, 1, sizeof(id), f); // comment string if(m_lpszSongComments) fwrite(&m_lpszSongComments[0], 1, strlen(m_lpszSongComments)+1, f); // Song global config id = (m_dwSongFlags & SONG_FILE_FLAGS); fwrite(&id, 1, sizeof(id), f); id = m_nDefaultGlobalVolume; fwrite(&id, 1, sizeof(id), f); id = m_nSamplePreAmp; fwrite(&id, 1, sizeof(id), f); id = m_nDefaultSpeed; fwrite(&id, 1, sizeof(id), f); id = m_nDefaultTempo; fwrite(&id, 1, sizeof(id), f); // Song channels data // number of channels id = m_nChannels; fwrite(&id, 1, sizeof(id), f); // channel name string length id = MAX_CHANNELNAME; fwrite(&id, 1, sizeof(id), f); // channel config data for(i=0; i<m_nChannels; i++){ id = ChnSettings[i].nPan; fwrite(&id, 1, sizeof(id), f); id = ChnSettings[i].dwFlags; fwrite(&id, 1, sizeof(id), f); id = ChnSettings[i].nVolume; fwrite(&id, 1, sizeof(id), f); fwrite(&ChnSettings[i].szName[0], 1, MAX_CHANNELNAME, f); } // Song mix plugins // mix plugins data length id = SaveMixPlugins(NULL, TRUE); fwrite(&id, 1, sizeof(id), f); // mix plugins data SaveMixPlugins(f, FALSE); // Song midi config // midi cfg data length id = sizeof(MODMIDICFG); fwrite(&id, 1, sizeof(id), f); // midi cfg fwrite(&m_MidiCfg, 1, sizeof(MODMIDICFG), f); // Song Instruments // number of instruments id = m_nInstruments; fwrite(&id, 1, sizeof(id), f); // path name string length id = _MAX_PATH; fwrite(&id, 1, sizeof(id), f); // instruments' path for(i=0; i<m_nInstruments; i++) fwrite(&m_szInstrumentPath[i][0], 1, _MAX_PATH, f); // Song Orders // order array size id = Order.size(); fwrite(&id, 1, sizeof(id), f); // order array Order.WriteAsByte(f, id); // Song Patterns // number of patterns id = MAX_PATTERNS; fwrite(&id, 1, sizeof(id), f); // number of pattern name strings modplug::tracker::patternindex_t numNamedPats = Patterns.GetNumNamedPatterns(); numNamedPats = bad_min(numNamedPats, MAX_PATTERNS); id = numNamedPats; fwrite(&id, 1, sizeof(id), f); // length of a pattern name string id = MAX_PATTERNNAME; fwrite(&id, 1, sizeof(id), f); // pattern name string for(modplug::tracker::patternindex_t nPat = 0; nPat < numNamedPats; nPat++) { char name[MAX_PATTERNNAME]; MemsetZero(name); Patterns[nPat].GetName(name, MAX_PATTERNNAME); fwrite(name, 1, MAX_PATTERNNAME, f); } // modcommand data length id = sizeof(modplug::tracker::modevent_t); fwrite(&id, 1, sizeof(id), f); // patterns data content for(UINT npat=0; npat<MAX_PATTERNS; npat++){ // pattern size (number of rows) id = Patterns[npat] ? Patterns[npat].GetNumRows() : 0; fwrite(&id, 1, sizeof(id), f); // pattern data if(Patterns[npat] && Patterns[npat].GetNumRows()) Patterns[npat].WriteITPdata(f); //fwrite(Patterns[npat], 1, m_nChannels * Patterns[npat].GetNumRows() * sizeof(modplug::tracker::modcommand_t), f); } // Song lonely (instrument-less) samples // Write original number of samples id = m_nSamples; fwrite(&id, 1, sizeof(id), f); vector<bool> sampleUsed(m_nSamples, false); // Mark samples used in instruments for(i=0; i<m_nInstruments; i++) { if(Instruments[i + 1] != nullptr) { modinstrument_t *p = Instruments[i + 1]; for(j = 0; j < 128; j++) { if(p->Keyboard[j] > 0 && p->Keyboard[j] <= m_nSamples) sampleUsed[p->Keyboard[j] - 1] = true; } } } // Count samples not used in any instrument i = 0; for(j = 1; j <= m_nSamples; j++) if(!sampleUsed[j - 1] && Samples[j].sample_data) i++; id = i; fwrite(&id, 1, sizeof(id), f); // Write samples not used in any instrument (help, this looks like duplicate code!) ITSAMPLESTRUCT itss; for(UINT nsmp=1; nsmp<=m_nSamples; nsmp++) { if(!sampleUsed[nsmp - 1] && Samples[nsmp].sample_data) { modsample_t *psmp = &Samples[nsmp]; memset(&itss, 0, sizeof(itss)); memcpy(itss.filename, psmp->legacy_filename, 12); memcpy(itss.name, m_szNames[nsmp], 26); itss.id = LittleEndian(IT_IMPS); itss.gvl = (uint8_t)psmp->global_volume; itss.flags = 0x00; if(psmp->flags & CHN_LOOP) itss.flags |= 0x10; if(psmp->flags & CHN_SUSTAINLOOP) itss.flags |= 0x20; if(psmp->flags & CHN_PINGPONGLOOP) itss.flags |= 0x40; if(psmp->flags & CHN_PINGPONGSUSTAIN) itss.flags |= 0x80; itss.C5Speed = psmp->c5_samplerate; if (!itss.C5Speed) itss.C5Speed = 8363; itss.length = psmp->length; itss.loopbegin = psmp->loop_start; itss.loopend = psmp->loop_end; itss.susloopbegin = psmp->sustain_start; itss.susloopend = psmp->sustain_end; itss.vol = (uint8_t)(psmp->default_volume >> 2); itss.dfp = (uint8_t)(psmp->default_pan >> 2); itss.vit = autovibxm2it[psmp->vibrato_type & 7]; itss.vis = bad_min(psmp->vibrato_rate, 64); itss.vid = bad_min(psmp->vibrato_depth, 32); itss.vir = bad_min(psmp->vibrato_sweep, 255); //(psmp->vibrato_sweep < 64) ? psmp->vibrato_sweep * 4 : 255; if (psmp->flags & CHN_PANNING) itss.dfp |= 0x80; if ((psmp->sample_data) && (psmp->length)) itss.cvt = 0x01; UINT flags = RS_PCM8S; if(psmp->flags & CHN_STEREO) { flags = RS_STPCM8S; itss.flags |= 0x04; } if(psmp->flags & CHN_16BIT) { itss.flags |= 0x02; flags = (psmp->flags & CHN_STEREO) ? RS_STPCM16S : RS_PCM16S; } id = nsmp; fwrite(&id, 1, sizeof(id), f); itss.samplepointer = NULL; fwrite(&itss, 1, sizeof(ITSAMPLESTRUCT), f); id = WriteSample(NULL, psmp, flags); fwrite(&id, 1, sizeof(id), f); WriteSample(f, psmp, flags); } }