1 /*
2  * Schism Tracker - a cross-platform Impulse Tracker clone
3  * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4  * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5  * copyright (c) 2009 Storlek & Mrs. Brisby
6  * copyright (c) 2010-2012 Storlek
7  * URL: http://schismtracker.org/
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #define NEED_BYTESWAP
25 #define NEED_TIME
26 #include "headers.h"
27 
28 #include "it.h"
29 #include "sndfile.h"
30 #include "song.h"
31 #include "slurp.h"
32 #include "page.h"
33 #include "version.h"
34 
35 #include "fmt.h"
36 #include "dmoz.h"
37 
38 #include "it_defs.h"
39 
40 #include "snd_gm.h"
41 #include "midi.h"
42 #include "disko.h"
43 
44 #include <stdio.h>
45 #include <string.h>
46 #include <errno.h>
47 #include <assert.h>
48 
49 // ------------------------------------------------------------------------
50 
51 char song_filename[PATH_MAX + 1];
52 char song_basename[NAME_MAX + 1];
53 
54 // ------------------------------------------------------------------------
55 // replace any '\0' chars with spaces, mostly to make the string handling
56 // much easier.
57 // TODO | Maybe this should be done with the filenames and the song title
58 // TODO | as well? (though I've never come across any cases of either of
59 // TODO | these having null characters in them...)
60 
_fix_names(song_t * qq)61 static void _fix_names(song_t *qq)
62 {
63 	int c, n;
64 
65 	for (n = 1; n < MAX_INSTRUMENTS; n++) {
66 		for (c = 0; c < 25; c++)
67 			if (qq->samples[n].name[c] == 0)
68 				qq->samples[n].name[c] = 32;
69 		qq->samples[n].name[25] = 0;
70 
71 		if (!qq->instruments[n])
72 			continue;
73 		for (c = 0; c < 25; c++)
74 			if (qq->instruments[n]->name[c] == 0)
75 				qq->instruments[n]->name[c] = 32;
76 		qq->instruments[n]->name[25] = 0;
77 	}
78 }
79 
80 // ------------------------------------------------------------------------
81 // file stuff
82 
song_set_filename(const char * file)83 static void song_set_filename(const char *file)
84 {
85 	if (file && file[0]) {
86 		strncpy(song_filename, file, PATH_MAX);
87 		strncpy(song_basename, get_basename(file), NAME_MAX);
88 		song_filename[PATH_MAX] = '\0';
89 		song_basename[NAME_MAX] = '\0';
90 	} else {
91 		song_filename[0] = '\0';
92 		song_basename[0] = '\0';
93 	}
94 }
95 
96 // clear patterns => clear filename and save flag
97 // clear orderlist => clear title, message, and channel settings
song_new(int flags)98 void song_new(int flags)
99 {
100 	int i;
101 
102 	song_lock_audio();
103 
104 	song_stop_unlocked(0);
105 
106 	if ((flags & KEEP_PATTERNS) == 0) {
107 		song_set_filename(NULL);
108 		status.flags &= ~SONG_NEEDS_SAVE;
109 
110 		for (i = 0; i < MAX_PATTERNS; i++) {
111 			if (current_song->patterns[i]) {
112 				csf_free_pattern(current_song->patterns[i]);
113 				current_song->patterns[i] = NULL;
114 			}
115 			current_song->pattern_size[i] = 64;
116 			current_song->pattern_alloc_size[i] = 64;
117 		}
118 	}
119 	if ((flags & KEEP_SAMPLES) == 0) {
120 		for (i = 1; i < MAX_SAMPLES; i++) {
121 			if (current_song->samples[i].data) {
122 				csf_free_sample(current_song->samples[i].data);
123 			}
124 		}
125 		memset(current_song->samples, 0, sizeof(current_song->samples));
126 		for (i = 1; i < MAX_SAMPLES; i++) {
127 			current_song->samples[i].c5speed = 8363;
128 			current_song->samples[i].volume = 64 * 4;
129 			current_song->samples[i].global_volume = 64;
130 		}
131 	}
132 	if ((flags & KEEP_INSTRUMENTS) == 0) {
133 		for (i = 0; i < MAX_INSTRUMENTS; i++) {
134 			if (current_song->instruments[i]) {
135 				csf_free_instrument(current_song->instruments[i]);
136 				current_song->instruments[i] = NULL;
137 			}
138 		}
139 	}
140 	if ((flags & KEEP_ORDERLIST) == 0) {
141 		memset(current_song->orderlist, ORDER_LAST, sizeof(current_song->orderlist));
142 		memset(current_song->title, 0, sizeof(current_song->title));
143 		memset(current_song->message, 0, MAX_MESSAGE);
144 
145 		for (i = 0; i < 64; i++) {
146 			current_song->channels[i].volume = 64;
147 			current_song->channels[i].panning = 128;
148 			current_song->channels[i].flags = 0;
149 			current_song->voices[i].volume = 256;
150 			current_song->voices[i].global_volume = current_song->channels[i].volume;
151 			current_song->voices[i].panning = current_song->channels[i].panning;
152 			current_song->voices[i].flags = current_song->channels[i].flags;
153 			current_song->voices[i].cutoff = 0x7F;
154 		}
155 	}
156 
157 	current_song->repeat_count = 0;
158 	//song_stop();
159 
160 	csf_forget_history(current_song);
161 
162 	song_unlock_audio();
163 
164 	main_song_changed_cb();
165 }
166 
167 // ------------------------------------------------------------------------------------------------------------
168 
169 #define LOAD_SONG(x) fmt_##x##_load_song,
170 static fmt_load_song_func load_song_funcs[] = {
171 #include "fmt-types.h"
172 	NULL,
173 };
174 
175 
fmt_strerror(int n)176 const char *fmt_strerror(int n)
177 {
178 	switch (n) {
179 	case -LOAD_UNSUPPORTED:
180 		return "Unrecognised file type";
181 	case -LOAD_FORMAT_ERROR:
182 		return "File format error (corrupt?)";
183 	default:
184 		return strerror(errno);
185 	}
186 }
187 
188 // IT uses \r in song messages; replace errant \n's
message_convert_newlines(song_t * song)189 void message_convert_newlines(song_t *song) {
190 	int i = 0, len = strlen(song->message);
191 	for (i = 0; i < len; i++) {
192 		if (song->message[i] == '\n') {
193 			song->message[i] = '\r';
194 		}
195 	}
196 }
197 
song_create_load(const char * file)198 song_t *song_create_load(const char *file)
199 {
200 	fmt_load_song_func *func;
201 	int ok = 0, err = 0;
202 
203 	slurp_t *s = slurp(file, NULL, 0);
204 	if (!s)
205 		return NULL;
206 
207 	song_t *newsong = csf_allocate();
208 
209 	if (current_song) {
210 		newsong->mix_flags = current_song->mix_flags;
211 		csf_set_wave_config(newsong,
212 			current_song->mix_frequency,
213 			current_song->mix_bits_per_sample,
214 			current_song->mix_channels);
215 
216 		// loaders might override these
217 		newsong->row_highlight_major = current_song->row_highlight_major;
218 		newsong->row_highlight_minor = current_song->row_highlight_minor;
219 		csf_copy_midi_cfg(newsong, current_song);
220 	}
221 
222 	for (func = load_song_funcs; *func && !ok; func++) {
223 		slurp_rewind(s);
224 		switch ((*func)(newsong, s, 0)) {
225 		case LOAD_SUCCESS:
226 			err = 0;
227 			ok = 1;
228 			break;
229 		case LOAD_UNSUPPORTED:
230 			err = -LOAD_UNSUPPORTED;
231 			continue;
232 		case LOAD_FORMAT_ERROR:
233 			err = -LOAD_FORMAT_ERROR;
234 			break;
235 		case LOAD_FILE_ERROR:
236 			err = errno;
237 			break;
238 		}
239 		if (err) {
240 			csf_free(newsong);
241 			unslurp(s);
242 			errno = err;
243 			return NULL;
244 		}
245 	}
246 
247 	unslurp(s);
248 
249 	if (err) {
250 		// awwww, nerts!
251 		csf_free(newsong);
252 		errno = err;
253 		return NULL;
254 	}
255 
256 	newsong->stop_at_order = newsong->stop_at_row = -1;
257 	message_convert_newlines(newsong);
258 	message_reset_selection();
259 
260 	return newsong;
261 }
262 
song_load_unchecked(const char * file)263 int song_load_unchecked(const char *file)
264 {
265 	const char *base = get_basename(file);
266 	int was_playing;
267 	song_t *newsong;
268 
269 	// IT stops the song even if the new song can't be loaded
270 	if (status.flags & PLAY_AFTER_LOAD) {
271 		was_playing = (song_get_mode() == MODE_PLAYING);
272 	} else {
273 		was_playing = 0;
274 		song_stop();
275 	}
276 
277 	log_nl();
278 	log_nl();
279 	log_appendf(2, "Loading %s", base);
280 	log_underline(strlen(base) + 8);
281 
282 	newsong = song_create_load(file);
283 	if (!newsong) {
284 		log_appendf(4, " %s", fmt_strerror(errno));
285 		return 0;
286 	}
287 
288 
289 	song_set_filename(file);
290 
291 	song_lock_audio();
292 	csf_free(current_song);
293 	current_song = newsong;
294 	current_song->repeat_count = 0;
295 	max_channels_used = 0;
296 	_fix_names(current_song);
297 	song_stop_unlocked(0);
298 	song_unlock_audio();
299 
300 	if (was_playing && (status.flags & PLAY_AFTER_LOAD))
301 		song_start();
302 
303 	main_song_changed_cb();
304 
305 	status.flags &= ~SONG_NEEDS_SAVE;
306 
307 	// print out some stuff
308 	const char *tid = current_song->tracker_id;
309 
310 	char fmt[] = " %d patterns, %d samples, %d instruments";
311 	int n, nsmp, nins;
312 	song_sample_t *smp;
313 	song_instrument_t **ins;
314 
315 	for (n = 0, smp = current_song->samples + 1, nsmp = 0; n < MAX_SAMPLES; n++, smp++)
316 		if (smp->data)
317 			nsmp++;
318 	for (n = 0, ins = current_song->instruments + 1, nins = 0; n < MAX_INSTRUMENTS; n++, ins++)
319 		if (*ins != NULL)
320 			nins++;
321 
322 	if (tid[0])
323 		log_appendf(5, " %s", tid);
324 	if (!nins)
325 		*strrchr(fmt, ',') = 0; // cut off 'instruments'
326 	log_appendf(5, fmt, csf_get_num_patterns(current_song), nsmp, nins);
327 
328 
329 	return 1;
330 }
331 
332 // ------------------------------------------------------------------------------------------------------------
333 
334 static song_instrument_t blank_instrument; // should be zero, it's coming from bss
335 
336 // set iti_file if saving an instrument to disk by itself
_save_it_instrument(int n,disko_t * fp,int iti_file)337 static void _save_it_instrument(int n, disko_t *fp, int iti_file)
338 {
339 	n++; // FIXME: this is dumb; really all the numbering should be one-based to make it simple
340 
341 	struct it_instrument iti = {};
342 	song_instrument_t *i = current_song->instruments[n];
343 
344 	if (!i)
345 		i = &blank_instrument;
346 
347 	// envelope: flags num lpb lpe slb sle data[25*3] reserved
348 
349 	iti.id = bswapLE32(0x49504D49); // IMPI
350 	strncpy((char *) iti.filename, (char *) i->filename, 12);
351 	iti.zero = 0;
352 	iti.nna = i->nna;
353 	iti.dct = i->dct;
354 	iti.dca = i->dca;
355 	iti.fadeout = bswapLE16(i->fadeout >> 5);
356 	iti.pps = i->pitch_pan_separation;
357 	iti.ppc = i->pitch_pan_center;
358 	iti.gbv = i->global_volume;
359 	iti.dfp = i->panning / 4;
360 	if (!(i->flags & ENV_SETPANNING))
361 		iti.dfp |= 0x80;
362 	iti.rv = i->vol_swing;
363 	iti.rp = i->pan_swing;
364 	if (iti_file) {
365 		iti.trkvers = bswapLE16(0x1000 | ver_cwtv);
366 	}
367 	// reserved1
368 	strncpy((char *) iti.name, (char *) i->name, 25);
369 	iti.name[25] = 0;
370 	iti.ifc = i->ifc;
371 	iti.ifr = i->ifr;
372 	iti.mch = 0;
373 	if(i->midi_channel_mask >= 0x10000)
374 	{
375 	    iti.mch = i->midi_channel_mask - 0x10000;
376 	    if(iti.mch <= 16) iti.mch = 16;
377 	}
378 	else if(i->midi_channel_mask & 0xFFFF)
379 	{
380 	    iti.mch = 1;
381 	    while(!(i->midi_channel_mask & (1 << (iti.mch-1)))) ++iti.mch;
382 	}
383 	iti.mpr = i->midi_program;
384 	iti.mbank = bswapLE16(i->midi_bank);
385 
386 	static int iti_map[255];
387 	static int iti_invmap[255];
388 	static int iti_nalloc = 0;
389 
390 	iti_nalloc = 0;
391 	for (int j = 0; j < 255; j++) {
392 		iti_map[j] = -1;
393 	}
394 	for (int j = 0; j < 120; j++) {
395 		if (iti_file) {
396 			int o = i->sample_map[j];
397 			if (o > 0 && o < 255 && iti_map[o] == -1) {
398 				iti_map[o] = iti_nalloc;
399 				iti_invmap[iti_nalloc] = o;
400 				iti_nalloc++;
401 			}
402 			iti.keyboard[2 * j + 1] = iti_map[o]+1;
403 		} else {
404 			iti.keyboard[2 * j + 1] = i->sample_map[j];
405 		}
406 		iti.keyboard[2 * j] = i->note_map[j] - 1;
407 	}
408 	if (iti_file) {
409 		iti.nos = (uint8_t)iti_nalloc;
410 	}
411 	// envelope stuff from modplug
412 	iti.volenv.flags = 0;
413 	iti.panenv.flags = 0;
414 	iti.pitchenv.flags = 0;
415 	if (i->flags & ENV_VOLUME) iti.volenv.flags |= 0x01;
416 	if (i->flags & ENV_VOLLOOP) iti.volenv.flags |= 0x02;
417 	if (i->flags & ENV_VOLSUSTAIN) iti.volenv.flags |= 0x04;
418 	if (i->flags & ENV_VOLCARRY) iti.volenv.flags |= 0x08;
419 	iti.volenv.num = i->vol_env.nodes;
420 	iti.volenv.lpb = i->vol_env.loop_start;
421 	iti.volenv.lpe = i->vol_env.loop_end;
422 	iti.volenv.slb = i->vol_env.sustain_start;
423 	iti.volenv.sle = i->vol_env.sustain_end;
424 	if (i->flags & ENV_PANNING) iti.panenv.flags |= 0x01;
425 	if (i->flags & ENV_PANLOOP) iti.panenv.flags |= 0x02;
426 	if (i->flags & ENV_PANSUSTAIN) iti.panenv.flags |= 0x04;
427 	if (i->flags & ENV_PANCARRY) iti.panenv.flags |= 0x08;
428 	iti.panenv.num = i->pan_env.nodes;
429 	iti.panenv.lpb = i->pan_env.loop_start;
430 	iti.panenv.lpe = i->pan_env.loop_end;
431 	iti.panenv.slb = i->pan_env.sustain_start;
432 	iti.panenv.sle = i->pan_env.sustain_end;
433 	if (i->flags & ENV_PITCH) iti.pitchenv.flags |= 0x01;
434 	if (i->flags & ENV_PITCHLOOP) iti.pitchenv.flags |= 0x02;
435 	if (i->flags & ENV_PITCHSUSTAIN) iti.pitchenv.flags |= 0x04;
436 	if (i->flags & ENV_PITCHCARRY) iti.pitchenv.flags |= 0x08;
437 	if (i->flags & ENV_FILTER) iti.pitchenv.flags |= 0x80;
438 	iti.pitchenv.num = i->pitch_env.nodes;
439 	iti.pitchenv.lpb = i->pitch_env.loop_start;
440 	iti.pitchenv.lpe = i->pitch_env.loop_end;
441 	iti.pitchenv.slb = i->pitch_env.sustain_start;
442 	iti.pitchenv.sle = i->pitch_env.sustain_end;
443 	for (int j = 0; j < 25; j++) {
444 		iti.volenv.data[3 * j] = i->vol_env.values[j];
445 		iti.volenv.data[3 * j + 1] = i->vol_env.ticks[j] & 0xFF;
446 		iti.volenv.data[3 * j + 2] = i->vol_env.ticks[j] >> 8;
447 		iti.panenv.data[3 * j] = i->pan_env.values[j] - 32;
448 		iti.panenv.data[3 * j + 1] = i->pan_env.ticks[j] & 0xFF;
449 		iti.panenv.data[3 * j + 2] = i->pan_env.ticks[j] >> 8;
450 		iti.pitchenv.data[3 * j] = i->pitch_env.values[j] - 32;
451 		iti.pitchenv.data[3 * j + 1] = i->pitch_env.ticks[j] & 0xFF;
452 		iti.pitchenv.data[3 * j + 2] = i->pitch_env.ticks[j] >> 8;
453 	}
454 
455 	// ITI files *need* to write 554 bytes due to alignment, but in a song it doesn't matter
456 	disko_write(fp, &iti, sizeof(iti));
457 	if (iti_file) {
458 		if (sizeof(iti) < 554) {
459 			for (int j = sizeof(iti); j < 554; j++) {
460 				disko_write(fp, "\x0", 1);
461 			}
462 		}
463 		assert(sizeof(iti) <= 554);
464 
465 		unsigned int qp = 554;
466 		/* okay, now go through samples */
467 		for (int j = 0; j < iti_nalloc; j++) {
468 			int o = iti_invmap[ j ];
469 
470 			iti_map[o] = qp;
471 			qp += 80; /* header is 80 bytes */
472 			save_its_header(fp, current_song->samples + o);
473 		}
474 		for (int j = 0; j < iti_nalloc; j++) {
475 			unsigned int op, tmp;
476 
477 			int o = iti_invmap[ j ];
478 
479 			song_sample_t *smp = current_song->samples + o;
480 
481 			op = disko_tell(fp);
482 			tmp = bswapLE32(op);
483 			disko_seek(fp, iti_map[o]+0x48, SEEK_SET);
484 			disko_write(fp, &tmp, 4);
485 			disko_seek(fp, op, SEEK_SET);
486 			csf_write_sample(fp, smp, SF_LE | SF_PCMS
487 					| ((smp->flags & CHN_16BIT) ? SF_16 : SF_8)
488 					| ((smp->flags & CHN_STEREO) ? SF_SS : SF_M),
489 					UINT32_MAX);
490 		}
491 	}
492 }
493 
494 // NOBODY expects the Spanish Inquisition!
_save_it_pattern(disko_t * fp,song_note_t * pat,int patsize)495 static void _save_it_pattern(disko_t *fp, song_note_t *pat, int patsize)
496 {
497 	song_note_t *noteptr = pat;
498 	song_note_t lastnote[64] = {};
499 	uint8_t initmask[64] = {};
500 	uint8_t lastmask[64];
501 	unsigned short pos = 0;
502 	uint8_t data[65536];
503 
504 	memset(lastmask, 0xff, 64);
505 
506 	for (int row = 0; row < patsize; row++) {
507 		for (int chan = 0; chan < 64; chan++, noteptr++) {
508 			uint8_t m = 0;  // current mask
509 			int vol = -1;
510 			unsigned int note = noteptr->note;
511 			uint8_t effect = noteptr->effect, param = noteptr->param;
512 
513 			if (note) {
514 				m |= 1;
515 				if (note < 0x80)
516 					note--;
517 			}
518 			if (noteptr->instrument) m |= 2;
519 			switch (noteptr->voleffect) {
520 			default:                                                       break;
521 			case VOLFX_VOLUME:         vol = MIN(noteptr->volparam, 64);       break;
522 			case VOLFX_FINEVOLUP:      vol = MIN(noteptr->volparam,  9) +  65; break;
523 			case VOLFX_FINEVOLDOWN:    vol = MIN(noteptr->volparam,  9) +  75; break;
524 			case VOLFX_VOLSLIDEUP:     vol = MIN(noteptr->volparam,  9) +  85; break;
525 			case VOLFX_VOLSLIDEDOWN:   vol = MIN(noteptr->volparam,  9) +  95; break;
526 			case VOLFX_PORTADOWN:      vol = MIN(noteptr->volparam,  9) + 105; break;
527 			case VOLFX_PORTAUP:        vol = MIN(noteptr->volparam,  9) + 115; break;
528 			case VOLFX_PANNING:        vol = MIN(noteptr->volparam, 64) + 128; break;
529 			case VOLFX_VIBRATODEPTH:   vol = MIN(noteptr->volparam,  9) + 203; break;
530 			case VOLFX_VIBRATOSPEED:   vol = 203;                         break;
531 			case VOLFX_TONEPORTAMENTO: vol = MIN(noteptr->volparam,  9) + 193; break;
532 			}
533 			if (vol != -1) m |= 4;
534 			csf_export_s3m_effect(&effect, &param, 1);
535 			if (effect || param) m |= 8;
536 			if (!m) continue;
537 
538 			if (m & 1) {
539 				if ((note == lastnote[chan].note) && (initmask[chan] & 1)) {
540 					m &= ~1;
541 					m |= 0x10;
542 				} else {
543 					lastnote[chan].note = note;
544 					initmask[chan] |= 1;
545 				}
546 			}
547 			if (m & 2) {
548 				if ((noteptr->instrument == lastnote[chan].instrument) && (initmask[chan] & 2)) {
549 					m &= ~2;
550 					m |= 0x20;
551 				} else {
552 					lastnote[chan].instrument = noteptr->instrument;
553 					initmask[chan] |= 2;
554 				}
555 			}
556 			if (m & 4) {
557 				if ((vol == lastnote[chan].volparam) && (initmask[chan] & 4)) {
558 					m &= ~4;
559 					m |= 0x40;
560 				} else {
561 					lastnote[chan].volparam = vol;
562 					initmask[chan] |= 4;
563 				}
564 			}
565 			if (m & 8) {
566 				if ((effect == lastnote[chan].effect) && (param == lastnote[chan].param)
567 				    && (initmask[chan] & 8)) {
568 					m &= ~8;
569 					m |= 0x80;
570 				} else {
571 					lastnote[chan].effect = effect;
572 					lastnote[chan].param = param;
573 					initmask[chan] |= 8;
574 				}
575 			}
576 			if (m == lastmask[chan]) {
577 				data[pos++] = chan + 1;
578 			} else {
579 				lastmask[chan] = m;
580 				data[pos++] = (chan + 1) | 0x80;
581 				data[pos++] = m;
582 			}
583 			if (m & 1) data[pos++] = note;
584 			if (m & 2) data[pos++] = noteptr->instrument;
585 			if (m & 4) data[pos++] = vol;
586 			if (m & 8) {
587 				data[pos++] = effect;
588 				data[pos++] = param;
589 			}
590 		}                       // end channel
591 		data[pos++] = 0;
592 	}                               // end row
593 
594 	// write the data to the file (finally!)
595 	unsigned short h[4] = {0};
596 	h[0] = bswapLE16(pos);
597 	h[1] = bswapLE16(patsize);
598 	// h[2] and h[3] are meaningless
599 	disko_write(fp, &h, 8);
600 	disko_write(fp, data, pos);
601 }
602 
603 // why on earth isn't this using the 'song' parameter? will finding this out hurt my head?
_save_it(disko_t * fp,UNUSED song_t * song)604 static int _save_it(disko_t *fp, UNUSED song_t *song)
605 {
606 	struct it_file hdr = {};
607 	int n;
608 	int nord, nins, nsmp, npat;
609 	int msglen = strlen(current_song->message);
610 	int warned_adlib = 0;
611 	uint32_t para_ins[256], para_smp[256], para_pat[256];
612 	// how much extra data is stuffed between the parapointers and the rest of the file
613 	// (2 bytes for edit history length, and 8 per entry including the current session)
614 	uint32_t extra = 2 + 8 * current_song->histlen + 8;
615 
616 	// TODO complain about nonstandard stuff? or just stop saving it to begin with
617 
618 	/* IT always saves at least two orders -- and requires an extra order at the end (which gets chopped!)
619 	However, the loader refuses to load files with too much data in the orderlist, so in the pathological
620 	case where order 255 has data, writing an extra 0xFF at the end will result in a file that can't be
621 	loaded back (for now). Eventually this can be fixed, but at least for a while it's probably a great
622 	idea not to save things that other versions won't load. */
623 	nord = csf_get_num_orders(current_song);
624 	nord = CLAMP(nord + 1, 2, MAX_ORDERS);
625 
626 	nins = csf_get_num_instruments(current_song);
627 	nsmp = csf_get_num_samples(current_song);
628 
629 	// IT always saves at least one pattern.
630 	npat = csf_get_num_patterns(current_song) ?: 1;
631 
632 	hdr.id = bswapLE32(0x4D504D49); // IMPM
633 	strncpy((char *) hdr.songname, current_song->title, 25);
634 	hdr.songname[25] = 0;
635 	hdr.hilight_major = current_song->row_highlight_major;
636 	hdr.hilight_minor = current_song->row_highlight_minor;
637 	hdr.ordnum = bswapLE16(nord);
638 	hdr.insnum = bswapLE16(nins);
639 	hdr.smpnum = bswapLE16(nsmp);
640 	hdr.patnum = bswapLE16(npat);
641 	// No one else seems to be using the cwtv's tracker id number, so I'm gonna take 1. :)
642 	hdr.cwtv = bswapLE16(0x1000 | ver_cwtv); // cwtv 0xtxyy = tracker id t, version x.yy
643 	// compat:
644 	//     really simple IT files = 1.00 (when?)
645 	//     "normal" = 2.00
646 	//     vol col effects = 2.08
647 	//     pitch wheel depth = 2.13
648 	//     embedded midi config = 2.13
649 	//     row highlight = 2.13 (doesn't necessarily affect cmwt)
650 	//     compressed samples = 2.14
651 	//     instrument filters = 2.17
652 	hdr.cmwt = bswapLE16(0x0214);   // compatible with IT 2.14
653 	for (n = 1; n < nins; n++) {
654 		song_instrument_t *i = current_song->instruments[n];
655 		if (!i) continue;
656 		if (i->flags & ENV_FILTER) {
657 			hdr.cmwt = bswapLE16(0x0217);
658 			break;
659 		}
660 	}
661 
662 	hdr.flags = 0;
663 	hdr.special = 2 | 4;            // 2 = edit history, 4 = row highlight
664 
665 	if (song_is_stereo())               hdr.flags |= 1;
666 	if (song_is_instrument_mode())      hdr.flags |= 4;
667 	if (song_has_linear_pitch_slides()) hdr.flags |= 8;
668 	if (song_has_old_effects())         hdr.flags |= 16;
669 	if (song_has_compatible_gxx())      hdr.flags |= 32;
670 	if (midi_flags & MIDI_PITCHBEND) {
671 		hdr.flags |= 64;
672 		hdr.pwd = midi_pitch_depth;
673 	}
674 	if (current_song->flags & SONG_EMBEDMIDICFG) {
675 		hdr.flags |= 128;
676 		hdr.special |= 8;
677 		extra += sizeof(midi_config_t);
678 	}
679 	hdr.flags = bswapLE16(hdr.flags);
680 	if (msglen) {
681 		hdr.special |= 1;
682 		msglen++;
683 	}
684 	hdr.special = bswapLE16(hdr.special);
685 
686 	// 16+ = reserved (always off?)
687 	hdr.globalvol = current_song->initial_global_volume;
688 	hdr.mv = current_song->mixing_volume;
689 	hdr.speed = current_song->initial_speed;
690 	hdr.tempo = current_song->initial_tempo;
691 	hdr.sep = current_song->pan_separation;
692 	if (msglen) {
693 		hdr.msgoffset = bswapLE32(extra + 0xc0 + nord + 4 * (nins + nsmp + npat));
694 		hdr.msglength = bswapLE16(msglen);
695 	}
696 	hdr.reserved = bswapLE32(ver_reserved);
697 
698 	for (n = 0; n < 64; n++) {
699 		hdr.chnpan[n] = ((current_song->channels[n].flags & CHN_SURROUND)
700 				 ? 100 : (current_song->channels[n].panning / 4));
701 		hdr.chnvol[n] = current_song->channels[n].volume;
702 		if (current_song->channels[n].flags & CHN_MUTE)
703 			hdr.chnpan[n] += 128;
704 	}
705 
706 	disko_write(fp, &hdr, sizeof(hdr));
707 	disko_write(fp, current_song->orderlist, nord);
708 
709 	// we'll get back to these later
710 	disko_write(fp, para_ins, 4*nins);
711 	disko_write(fp, para_smp, 4*nsmp);
712 	disko_write(fp, para_pat, 4*npat);
713 
714 	// edit history (see scripts/timestamp.py)
715 	// Should™ be fully compatible with Impulse Tracker.
716 	struct timeval savetime, elapsed;
717 	struct tm loadtm;
718 	uint16_t h;
719 	//x86/x64 compatibility
720 	time_t thetime = current_song->editstart.tv_sec;
721 	localtime_r(&thetime, &loadtm);
722 	gettimeofday(&savetime, NULL);
723 	timersub(&savetime, &current_song->editstart, &elapsed);
724 
725 	// item count
726 	h = current_song->histlen + 1;
727 	h = bswapLE16(h);
728 	disko_write(fp, &h, 2);
729 	// old data
730 	disko_write(fp, current_song->histdata, 8 * current_song->histlen);
731 	// 16-bit date
732 	h = loadtm.tm_mday | ((loadtm.tm_mon + 1) << 5) | ((loadtm.tm_year - 80) << 9);
733 	h = bswapLE16(h);
734 	disko_write(fp, &h, 2);
735 	// 16-bit time
736 	h = (loadtm.tm_sec / 2) | (loadtm.tm_min << 5) | (loadtm.tm_hour << 11);
737 	h = bswapLE16(h);
738 	disko_write(fp, &h, 2);
739 	// 32-bit DOS tick count (tick = 1/18.2 second; 54945 * 18.2 = 999999 which is Close Enough)
740 	uint32_t ticks = elapsed.tv_sec * 182 / 10 + elapsed.tv_usec / 54945;
741 	ticks = bswapLE32(ticks);
742 	disko_write(fp, &ticks, 4);
743 
744 	// here comes MIDI configuration
745 	// here comes MIDI configuration
746 	// right down MIDI configuration lane
747 	if (current_song->flags & SONG_EMBEDMIDICFG) {
748 		disko_write(fp, &current_song->midi_config, sizeof(current_song->midi_config));
749 	}
750 
751 	disko_write(fp, current_song->message, msglen);
752 
753 	// instruments, samples, and patterns
754 	for (n = 0; n < nins; n++) {
755 		para_ins[n] = disko_tell(fp);
756 		para_ins[n] = bswapLE32(para_ins[n]);
757 		_save_it_instrument(n, fp, 0);
758 	}
759 	for (n = 0; n < nsmp; n++) {
760 		// the sample parapointers are byte-swapped later
761 		para_smp[n] = disko_tell(fp);
762 		save_its_header(fp, current_song->samples + n + 1);
763 	}
764 	for (n = 0; n < npat; n++) {
765 		if (csf_pattern_is_empty(current_song, n)) {
766 			para_pat[n] = 0;
767 		} else {
768 			para_pat[n] = disko_tell(fp);
769 			para_pat[n] = bswapLE32(para_pat[n]);
770 			_save_it_pattern(fp, current_song->patterns[n], current_song->pattern_size[n]);
771 		}
772 	}
773 
774 	// sample data
775 	for (n = 0; n < nsmp; n++) {
776 		unsigned int tmp, op;
777 		song_sample_t *smp = current_song->samples + (n + 1);
778 
779 		// Always save the data pointer, even if there's not actually any data being pointed to
780 		op = disko_tell(fp);
781 		tmp = bswapLE32(op);
782 		disko_seek(fp, para_smp[n]+0x48, SEEK_SET);
783 		disko_write(fp, &tmp, 4);
784 		disko_seek(fp, op, SEEK_SET);
785 		if (smp->data)
786 			csf_write_sample(fp, smp, SF_LE | SF_PCMS
787 					| ((smp->flags & CHN_16BIT) ? SF_16 : SF_8)
788 					| ((smp->flags & CHN_STEREO) ? SF_SS : SF_M),
789 					UINT32_MAX);
790 		// done using the pointer internally, so *now* swap it
791 		para_smp[n] = bswapLE32(para_smp[n]);
792 
793 		if (!warned_adlib && smp->flags & CHN_ADLIB) {
794 			log_appendf(4, " Warning: AdLib samples unsupported in IT format");
795 			warned_adlib = 1;
796 		}
797 	}
798 
799 	// rewrite the parapointers
800 	disko_seek(fp, 0xc0 + nord, SEEK_SET);
801 	disko_write(fp, para_ins, 4*nins);
802 	disko_write(fp, para_smp, 4*nsmp);
803 	disko_write(fp, para_pat, 4*npat);
804 
805 	return SAVE_SUCCESS;
806 }
807 
808 /* ------------------------------------------------------------------------- */
809 
810 const struct save_format song_save_formats[] = {
811 	{"IT", "Impulse Tracker", ".it", {.save_song = _save_it}},
812 	{"S3M", "Scream Tracker 3", ".s3m", {.save_song = fmt_s3m_save_song}},
813 	{"MOD", "Amiga ProTracker", ".mod", {.save_song = fmt_mod_save_song}},
814 	{.label = NULL}
815 };
816 
817 #define EXPORT_FUNCS(t) \
818 	fmt_##t##_export_head, fmt_##t##_export_silence, fmt_##t##_export_body, fmt_##t##_export_tail
819 
820 const struct save_format song_export_formats[] = {
821 	{"WAV", "WAV", ".wav", {.export = {EXPORT_FUNCS(wav), 0}}},
822 	{"MWAV", "WAV multi-write", ".wav", {.export = {EXPORT_FUNCS(wav), 1}}},
823 	{"AIFF", "Audio IFF", ".aiff", {.export = {EXPORT_FUNCS(aiff), 0}}},
824 	{"MAIFF", "Audio IFF multi-write", ".aiff", {.export = {EXPORT_FUNCS(aiff), 1}}},
825 	{.label = NULL}
826 };
827 // <distance> and maiff sounds like something you'd want to hug
828 // <distance> .. dont ask
829 
830 const struct save_format sample_save_formats[] = {
831 	{"ITS", "Impulse Tracker", ".its", {.save_sample = fmt_its_save_sample}},
832 	//{"S3I", "Scream Tracker", ".s3i", {.save_sample = fmt_s3i_save_sample}},
833 	{"AIFF", "Audio IFF", ".aiff", {.save_sample = fmt_aiff_save_sample}},
834 	{"AU", "Sun/NeXT", ".au", {.save_sample = fmt_au_save_sample}},
835 	{"WAV", "WAV", ".wav", {.save_sample = fmt_wav_save_sample}},
836 	{"RAW", "Raw", ".raw", {.save_sample = fmt_raw_save_sample}},
837 	{.label = NULL}
838 };
839 
get_save_format(const struct save_format * formats,const char * label)840 static const struct save_format *get_save_format(const struct save_format *formats, const char *label)
841 {
842 	int n;
843 
844 	if (!label) {
845 		// why would this happen, ever?
846 		log_appendf(4, "No file type given, very weird! (Try a different filename?)");
847 		return NULL;
848 	}
849 
850 	for (n = 0; formats[n].label; n++)
851 		if (strcmp(formats[n].label, label) == 0)
852 			return formats + n;
853 
854 	log_appendf(4, "Unknown save format %s", label);
855 	return NULL;
856 }
857 
858 
mangle_filename(const char * in,const char * mid,const char * ext)859 static char *mangle_filename(const char *in, const char *mid, const char *ext)
860 {
861 	char *ret;
862 	const char *iext;
863 	size_t baselen, rlen;
864 
865 	iext = get_extension(in);
866 	rlen = baselen = iext - in;
867 	if (mid)
868 		rlen += strlen(mid);
869 	if (iext[0])
870 		rlen += strlen(iext);
871 	else if (ext)
872 		rlen += strlen(ext);
873 	ret = malloc(rlen + 1); /* room for terminating \0 */
874 	if (!ret)
875 		return NULL;
876 	strncpy(ret, in, baselen);
877 	ret[baselen] = '\0';
878 	if (mid)
879 		strcat(ret, mid);
880 	/* maybe output a warning if iext and ext differ? */
881 	if (iext[0])
882 		strcat(ret, iext);
883 	else if (ext)
884 		strcat(ret, ext);
885 	return ret;
886 }
887 
song_export(const char * filename,const char * type)888 int song_export(const char *filename, const char *type)
889 {
890 	const struct save_format *format = get_save_format(song_export_formats, type);
891 	const char *mid;
892 	char *mangle;
893 	int r;
894 
895 	if (!format)
896 		return SAVE_INTERNAL_ERROR;
897 
898 	mid = (format->f.export.multi && strcasestr(filename, "%c") == NULL) ? ".%c" : NULL;
899 	mangle = mangle_filename(filename, mid, format->ext);
900 
901 	log_nl();
902 	log_nl();
903 	log_appendf(2, "Exporting to %s", format->name);
904 	log_underline(strlen(format->name) + 13);
905 
906 	/* disko does the rest of the log messages itself */
907 	r = disko_export_song(mangle, format);
908 	free(mangle);
909 	switch (r) {
910 	case DW_OK:
911 		return SAVE_SUCCESS;
912 	case DW_ERROR:
913 		return SAVE_FILE_ERROR;
914 	default:
915 		return SAVE_INTERNAL_ERROR;
916 	}
917 }
918 
919 
song_save(const char * filename,const char * type)920 int song_save(const char *filename, const char *type)
921 {
922 	int ret, backup;
923 	const struct save_format *format = get_save_format(song_save_formats, type);
924 	char *mangle;
925 
926 	if (!format)
927 		return SAVE_INTERNAL_ERROR;
928 
929 	mangle = mangle_filename(filename, NULL, format->ext);
930 
931 	log_nl();
932 	log_nl();
933 	log_appendf(2, "Saving %s module", format->name);
934 	log_underline(strlen(format->name) + 14);
935 
936 /* TODO: add or replace file extension as appropriate
937 
938 From IT 2.10 update:
939   - Automatic filename extension replacement on Ctrl-S, so that if you press
940     Ctrl-S after loading a .MOD, .669, .MTM or .XM, the filename will be
941     automatically modified to have a .IT extension.
942 
943 In IT, if the filename given has no extension ("basename"), then the extension for the proper file type
944 (IT/S3M) will be appended to the name.
945 A filename with an extension is not modified, even if the extension is blank. (as in "basename.")
946 
947 This brings up a rather odd bit of behavior: what happens when saving a file with the deliberately wrong
948 extension? Selecting the IT type and saving as "test.s3m" works just as one would expect: an IT file is
949 written, with the name "test.s3m". No surprises yet, but as soon as Ctrl-S is used, the filename is "fixed",
950 producing a second file called "test.it". The reverse happens when trying to save an S3M named "test.it" --
951 it's rewritten to "test.s3m".
952 Note that in these scenarios, Impulse Tracker *DOES NOT* check if an existing file by that name exists; it
953 will GLADLY overwrite the old "test.s3m" (or .it) with the renamed file that's being saved. Presumably this
954 is NOT intentional behavior.
955 
956 Another note: if the file could not be saved for some reason or another, Impulse Tracker pops up a dialog
957 saying "Could not save file". This can be seen rather easily by trying to save a file with a malformed name,
958 such as "abc|def.it". This dialog is presented both when saving from F10 and Ctrl-S.
959 */
960 
961 	disko_t *fp = disko_open(mangle);
962 	if (!fp) {
963 		log_perror(mangle);
964 		free(mangle);
965 		return SAVE_FILE_ERROR;
966 	}
967 
968 	ret = format->f.save_song(fp, current_song);
969 	if (ret != SAVE_SUCCESS)
970 		disko_seterror(fp, EINVAL);
971 	backup = ((status.flags & MAKE_BACKUPS)
972 		  ? (status.flags & NUMBERED_BACKUPS)
973 		  ? 65536 : 1 : 0);
974 	if (disko_close(fp, backup) == DW_ERROR && ret == SAVE_SUCCESS) {
975 		// this was not as successful as originally claimed!
976 		ret = SAVE_FILE_ERROR;
977 	}
978 
979 	switch (ret) {
980 	case SAVE_SUCCESS:
981 		status.flags &= ~SONG_NEEDS_SAVE;
982 		if (strcasecmp(song_filename, mangle))
983 			song_set_filename(mangle);
984 		log_appendf(5, " Done");
985 		break;
986 	case SAVE_FILE_ERROR:
987 		log_perror(mangle);
988 		break;
989 	case SAVE_INTERNAL_ERROR:
990 	default: // ???
991 		log_appendf(4, " Internal error saving song");
992 		break;
993 	}
994 
995 	free(mangle);
996 	return ret;
997 }
998 
song_save_sample(const char * filename,const char * type,song_sample_t * smp,int num)999 int song_save_sample(const char *filename, const char *type, song_sample_t *smp, int num)
1000 {
1001 	int ret;
1002 	const struct save_format *format = get_save_format(sample_save_formats, type);
1003 
1004 	if (!format)
1005 		return SAVE_INTERNAL_ERROR;
1006 
1007 	if (!filename || !filename[0]) {
1008 		status_text_flash("Error: Sample %d NOT saved! (%s)", num, "No Filename?");
1009 		return SAVE_INTERNAL_ERROR; // ?
1010 	}
1011 
1012 	disko_t *fp = disko_open(filename);
1013 	if (fp) {
1014 		ret = format->f.save_sample(fp, smp);
1015 		if (ret != SAVE_SUCCESS)
1016 			disko_seterror(fp, EINVAL);
1017 		if (disko_close(fp, 0) == DW_ERROR && ret == SAVE_SUCCESS) {
1018 			// this was not as successful as originally claimed!
1019 			ret = SAVE_FILE_ERROR;
1020 		}
1021 	} else {
1022 		ret = SAVE_FILE_ERROR;
1023 	}
1024 
1025 	switch (ret) {
1026 	case SAVE_SUCCESS:
1027 		status_text_flash("%s sample saved (sample %d)", format->name, num);
1028 		break;
1029 	case SAVE_FILE_ERROR:
1030 		status_text_flash("Error: Sample %d NOT saved! (%s)", num, "File Error");
1031 		log_perror(get_basename(filename));
1032 		break;
1033 	case SAVE_INTERNAL_ERROR:
1034 	default: // ???
1035 		status_text_flash("Error: Sample %d NOT saved! (%s)", num, "Internal error");
1036 		log_appendf(4, "Internal error saving sample");
1037 		break;
1038 	}
1039 
1040 	return ret;
1041 }
1042 
1043 // ------------------------------------------------------------------------
1044 
1045 // All of the sample's fields are initially zeroed except the filename (which is set to the sample's
1046 // basename and shouldn't be changed). A sample loader should not change anything in the sample until
1047 // it is sure that it can accept the file.
1048 // The title points to a buffer of 26 characters.
1049 
1050 #define LOAD_SAMPLE(x) fmt_##x##_load_sample,
1051 static fmt_load_sample_func load_sample_funcs[] = {
1052 #include "fmt-types.h"
1053 	NULL,
1054 };
1055 
1056 #define LOAD_INSTRUMENT(x) fmt_##x##_load_instrument,
1057 static fmt_load_instrument_func load_instrument_funcs[] = {
1058 #include "fmt-types.h"
1059 	NULL,
1060 };
1061 
1062 
song_clear_sample(int n)1063 void song_clear_sample(int n)
1064 {
1065 	song_lock_audio();
1066 	csf_destroy_sample(current_song, n);
1067 	memset(current_song->samples + n, 0, sizeof(song_sample_t));
1068 	current_song->samples[n].c5speed = 8363;
1069 	current_song->samples[n].volume = 64 * 4;
1070 	current_song->samples[n].global_volume = 64;
1071 	song_unlock_audio();
1072 }
1073 
song_copy_sample(int n,song_sample_t * src)1074 void song_copy_sample(int n, song_sample_t *src)
1075 {
1076 	memcpy(current_song->samples + n, src, sizeof(song_sample_t));
1077 
1078 	if (src->data) {
1079 		unsigned long bytelength = src->length;
1080 		if (src->flags & CHN_16BIT)
1081 			bytelength *= 2;
1082 		if (src->flags & CHN_STEREO)
1083 			bytelength *= 2;
1084 
1085 		current_song->samples[n].data = csf_allocate_sample(bytelength);
1086 		memcpy(current_song->samples[n].data, src->data, bytelength);
1087 	}
1088 }
1089 
song_load_instrument_ex(int target,const char * file,const char * libf,int n)1090 int song_load_instrument_ex(int target, const char *file, const char *libf, int n)
1091 {
1092 	slurp_t *s;
1093 	int r, x;
1094 
1095 	song_lock_audio();
1096 
1097 	/* 0. delete old samples */
1098 	if (current_song->instruments[target]) {
1099 		int sampmap[MAX_SAMPLES] = {};
1100 
1101 		/* init... */
1102 		for (unsigned int j = 0; j < 128; j++) {
1103 			x = current_song->instruments[target]->sample_map[j];
1104 			sampmap[x] = 1;
1105 		}
1106 		/* mark... */
1107 		for (unsigned int q = 0; q < MAX_INSTRUMENTS; q++) {
1108 			if ((int) q == target) continue;
1109 			if (!current_song->instruments[q]) continue;
1110 			for (unsigned int j = 0; j < 128; j++) {
1111 				x = current_song->instruments[q]->sample_map[j];
1112 				sampmap[x] = 0;
1113 			}
1114 		}
1115 		/* sweep! */
1116 		for (int j = 1; j < MAX_SAMPLES; j++) {
1117 			if (!sampmap[j]) continue;
1118 
1119 			csf_destroy_sample(current_song, j);
1120 			memset(current_song->samples + j, 0, sizeof(current_song->samples[j]));
1121 		}
1122 		/* now clear everything "empty" so we have extra slots */
1123 		for (int j = 1; j < MAX_SAMPLES; j++) {
1124 			if (csf_sample_is_empty(current_song->samples + j)) sampmap[j] = 0;
1125 		}
1126 	}
1127 
1128 	if (libf) { /* file is ignored */
1129 		int sampmap[MAX_SAMPLES] = {};
1130 
1131 		song_t *xl = song_create_load(libf);
1132 		if (!xl) {
1133 			log_appendf(4, "%s: %s", libf, fmt_strerror(errno));
1134 			song_unlock_audio();
1135 			return 0;
1136 		}
1137 
1138 		/* 1. find a place for all the samples */
1139 		for (unsigned int j = 0; j < 128; j++) {
1140 			x = xl->instruments[n]->sample_map[j];
1141 			if (!sampmap[x]) {
1142 				if (x > 0 && x < MAX_INSTRUMENTS) {
1143 					for (int k = 1; k < MAX_SAMPLES; k++) {
1144 						if (current_song->samples[k].length) continue;
1145 						sampmap[x] = k;
1146 						//song_sample *smp = (song_sample *)song_get_sample(k);
1147 
1148 						for (int c = 0; c < 25; c++) {
1149 							if (xl->samples[x].name[c] == 0)
1150 								xl->samples[x].name[c] = 32;
1151 						}
1152 						xl->samples[x].name[25] = 0;
1153 
1154 						song_copy_sample(k, &xl->samples[x]);
1155 						break;
1156 					}
1157 				}
1158 			}
1159 		}
1160 
1161 		/* transfer the instrument */
1162 		current_song->instruments[target] = xl->instruments[n];
1163 		xl->instruments[n] = NULL; /* dangle */
1164 
1165 		/* and rewrite! */
1166 		for (unsigned int k = 0; k < 128; k++) {
1167 			current_song->instruments[target]->sample_map[k] = sampmap[
1168 					current_song->instruments[target]->sample_map[k]
1169 			];
1170 		}
1171 
1172 		song_unlock_audio();
1173 		return 1;
1174 	}
1175 
1176 	/* okay, load an ITI file */
1177 	s = slurp(file, NULL, 0);
1178 	if (!s) {
1179 		log_perror(file);
1180 		song_unlock_audio();
1181 		return 0;
1182 	}
1183 
1184 	r = 0;
1185 	for (x = 0; load_instrument_funcs[x]; x++) {
1186 		r = load_instrument_funcs[x](s->data, s->length, target);
1187 		if (r) break;
1188 	}
1189 
1190 	unslurp(s);
1191 	song_unlock_audio();
1192 
1193 	return r;
1194 }
1195 
song_load_instrument(int n,const char * file)1196 int song_load_instrument(int n, const char *file)
1197 {
1198 	return song_load_instrument_ex(n,file,NULL,-1);
1199 }
1200 
song_preload_sample(dmoz_file_t * file)1201 int song_preload_sample(dmoz_file_t *file)
1202 {
1203 	// 0 is our "hidden sample"
1204 #define FAKE_SLOT 0
1205 	//csf_stop_sample(current_song, current_song->samples + FAKE_SLOT);
1206 	if (file->sample) {
1207 		song_sample_t *smp = song_get_sample(FAKE_SLOT);
1208 
1209 		song_lock_audio();
1210 		csf_destroy_sample(current_song, FAKE_SLOT);
1211 		song_copy_sample(FAKE_SLOT, file->sample);
1212 		strncpy(smp->name, file->title, 25);
1213 		smp->name[25] = 0;
1214 		strncpy(smp->filename, file->base, 12);
1215 		smp->filename[12] = 0;
1216 		song_unlock_audio();
1217 		return FAKE_SLOT;
1218 	}
1219 	// WARNING this function must return 0 or KEYJAZZ_NOINST
1220 	return song_load_sample(FAKE_SLOT, file->path) ? FAKE_SLOT : KEYJAZZ_NOINST;
1221 #undef FAKE_SLOT
1222 }
1223 
song_load_sample(int n,const char * file)1224 int song_load_sample(int n, const char *file)
1225 {
1226 	fmt_load_sample_func *load;
1227 	song_sample_t smp = {};
1228 
1229 	const char *base = get_basename(file);
1230 	slurp_t *s = slurp(file, NULL, 0);
1231 
1232 	if (s == NULL) {
1233 		log_perror(base);
1234 		return 0;
1235 	}
1236 
1237 	// set some default stuff
1238 	song_lock_audio();
1239 	csf_stop_sample(current_song, current_song->samples + n);
1240 	strncpy(smp.name, base, 25);
1241 
1242 	for (load = load_sample_funcs; *load; load++) {
1243 		if ((*load)(s->data, s->length, &smp)) {
1244 			break;
1245 		}
1246 	}
1247 
1248 	if (!load) {
1249 		unslurp(s);
1250 		log_perror(base);
1251 		song_unlock_audio();
1252 		return 0;
1253 	}
1254 
1255 	// this is after the loaders because i don't trust them, even though i wrote them ;)
1256 	strncpy(smp.filename, base, 12);
1257 	smp.filename[12] = 0;
1258 	smp.name[25] = 0;
1259 
1260 	csf_destroy_sample(current_song, n);
1261 	if (((unsigned char)smp.name[23]) == 0xFF) {
1262 		// don't load embedded samples
1263 		// (huhwhat?!)
1264 		smp.name[23] = ' ';
1265 	}
1266 	memcpy(&(current_song->samples[n]), &smp, sizeof(song_sample_t));
1267 	song_unlock_audio();
1268 
1269 	unslurp(s);
1270 
1271 	return 1;
1272 }
1273 
song_create_host_instrument(int smp)1274 void song_create_host_instrument(int smp)
1275 {
1276 	int ins = instrument_get_current();
1277 
1278 	if (csf_instrument_is_empty(current_song->instruments[smp]))
1279 		ins = smp;
1280 	else if ((status.flags & CLASSIC_MODE) || !csf_instrument_is_empty(current_song->instruments[ins]))
1281 		ins = csf_first_blank_instrument(current_song, 0);
1282 
1283 	if (ins > 0) {
1284 		song_init_instrument_from_sample(ins, smp);
1285 		status_text_flash("Sample assigned to Instrument %d", ins);
1286 	} else {
1287 		status_text_flash("Error: No available Instruments!");
1288 	}
1289 }
1290 
1291 // ------------------------------------------------------------------------
1292 
song_save_instrument(int n,const char * file)1293 int song_save_instrument(int n, const char *file)
1294 {
1295 	song_instrument_t *ins = current_song->instruments[n];
1296 
1297 	log_appendf(2, "Saving instrument %s", file);
1298 	if (!ins) {
1299 		/* this should never happen */
1300 		log_appendf(4, "Instrument %d: there is no spoon", n);
1301 		return 0;
1302 	}
1303 
1304 	if (file[0] == '\0') {
1305 		log_appendf(4, "Instrument %d: no filename", n);
1306 		return 0;
1307 	}
1308 	disko_t *fp = disko_open(file);
1309 	if (!fp) {
1310 		log_perror(get_basename(file));
1311 		return 0;
1312 	}
1313 	_save_it_instrument(n-1 /* grr.... */, fp, 1);
1314 	if (disko_close(fp, 0) == DW_ERROR) {
1315 		log_perror(get_basename(file));
1316 		return 0;
1317 	}
1318 	return 1;
1319 }
1320 
1321 // ------------------------------------------------------------------------
1322 // song information
1323 
song_get_filename(void)1324 const char *song_get_filename(void)
1325 {
1326 	return song_filename;
1327 }
1328 
song_get_basename(void)1329 const char *song_get_basename(void)
1330 {
1331 	return song_basename;
1332 }
1333 
1334 // ------------------------------------------------------------------------
1335 // sample library browsing
1336 
1337 // FIXME: unload the module when leaving the library 'directory'
1338 static song_t *library = NULL;
1339 
1340 
1341 // TODO: stat the file?
dmoz_read_instrument_library(const char * path,dmoz_filelist_t * flist,UNUSED dmoz_dirlist_t * dlist)1342 int dmoz_read_instrument_library(const char *path, dmoz_filelist_t *flist, UNUSED dmoz_dirlist_t *dlist)
1343 {
1344 	unsigned int j;
1345 	int x;
1346 
1347 	csf_stop_sample(current_song, current_song->samples + 0);
1348 	csf_free(library);
1349 
1350 	const char *base = get_basename(path);
1351 	library = song_create_load(path);
1352 	if (!library) {
1353 		log_appendf(4, "%s: %s", base, fmt_strerror(errno));
1354 		return -1;
1355 	}
1356 
1357 	for (int n = 1; n < MAX_INSTRUMENTS; n++) {
1358 		if (!library->instruments[n])
1359 			continue;
1360 
1361 		dmoz_file_t *file = dmoz_add_file(flist,
1362 			str_dup(path), str_dup(base), NULL, n);
1363 		file->title = str_dup(library->instruments[n]->name);
1364 
1365 		int count[128] = {};
1366 
1367 		file->sampsize = 0;
1368 		file->filesize = 0;
1369 		file->instnum = n;
1370 		for (j = 0; j < 128; j++) {
1371 			x = library->instruments[n]->sample_map[j];
1372 			if (!count[x]) {
1373 				if (x > 0 && x < MAX_INSTRUMENTS) {
1374 					file->filesize += library->samples[x].length;
1375 					file->sampsize++;
1376 				}
1377 			}
1378 			count[x]++;
1379 		}
1380 
1381 		file->type = TYPE_INST_ITI;
1382 		file->description = "Fishcakes";
1383 		// IT doesn't support this, despite it being useful.
1384 		// Simply "unrecognized"
1385 	}
1386 
1387 	return 0;
1388 }
1389 
1390 
dmoz_read_sample_library(const char * path,dmoz_filelist_t * flist,UNUSED dmoz_dirlist_t * dlist)1391 int dmoz_read_sample_library(const char *path, dmoz_filelist_t *flist, UNUSED dmoz_dirlist_t *dlist)
1392 {
1393 	csf_stop_sample(current_song, current_song->samples + 0);
1394 	csf_free(library);
1395 
1396 	const char *base = get_basename(path);
1397 	library = song_create_load(path);
1398 	if (!library) {
1399 		/* FIXME: try loading as an instrument before giving up */
1400 		log_appendf(4, "%s: %s", base, fmt_strerror(errno));
1401 		errno = ENOTDIR;
1402 		return -1;
1403 	}
1404 
1405 	for (int n = 1; n < MAX_SAMPLES; n++) {
1406 		if (library->samples[n].length) {
1407 			for (int c = 0; c < 25; c++) {
1408 				if (library->samples[n].name[c] == 0)
1409 					library->samples[n].name[c] = 32;
1410 				library->samples[n].name[25] = 0;
1411 			}
1412 			dmoz_file_t *file = dmoz_add_file(flist, str_dup(path), str_dup(base), NULL, n);
1413 			file->type = TYPE_SAMPLE_EXTD;
1414 			file->description = "Fishcakes"; // FIXME - what does IT say?
1415 			file->smp_speed = library->samples[n].c5speed;
1416 			file->smp_loop_start = library->samples[n].loop_start;
1417 			file->smp_loop_end = library->samples[n].loop_end;
1418 			file->smp_sustain_start = library->samples[n].sustain_start;
1419 			file->smp_sustain_end = library->samples[n].sustain_end;
1420 			file->smp_length = library->samples[n].length;
1421 			file->smp_flags = library->samples[n].flags;
1422 			file->smp_defvol = library->samples[n].volume>>2;
1423 			file->smp_gblvol = library->samples[n].global_volume;
1424 			file->smp_vibrato_speed = library->samples[n].vib_speed;
1425 			file->smp_vibrato_depth = library->samples[n].vib_depth;
1426 			file->smp_vibrato_rate = library->samples[n].vib_rate;
1427 			// don't screw this up...
1428 			if (((unsigned char)library->samples[n].name[23]) == 0xFF) {
1429 				library->samples[n].name[23] = ' ';
1430 			}
1431 			file->title = str_dup(library->samples[n].name);
1432 			file->sample = (song_sample_t *) library->samples + n;
1433 		}
1434 	}
1435 
1436 	return 0;
1437 }
1438 
1439 // ------------------------------------------------------------------------
1440 // instrument loader
1441 
instrument_loader_init(struct instrumentloader * ii,int slot)1442 song_instrument_t *instrument_loader_init(struct instrumentloader *ii, int slot)
1443 {
1444 	ii->expect_samples = 0;
1445 	ii->inst = song_get_instrument(slot);
1446 	ii->slot = slot;
1447 	ii->basex = 1;
1448 	memset(ii->sample_map, 0, sizeof(ii->sample_map));
1449 	return ii->inst;
1450 }
1451 
instrument_loader_abort(struct instrumentloader * ii)1452 int instrument_loader_abort(struct instrumentloader *ii)
1453 {
1454 	int n;
1455 	song_wipe_instrument(ii->slot);
1456 	for (n = 0; n < MAX_SAMPLES; n++) {
1457 		if (ii->sample_map[n]) {
1458 			song_clear_sample(ii->sample_map[n]-1);
1459 			ii->sample_map[n] = 0;
1460 		}
1461 	}
1462 	return 0;
1463 }
1464 
instrument_loader_sample(struct instrumentloader * ii,int slot)1465 int instrument_loader_sample(struct instrumentloader *ii, int slot)
1466 {
1467 	int x;
1468 
1469 	if (!slot) return 0;
1470 	if (ii->sample_map[slot]) return ii->sample_map[slot];
1471 	for (x = ii->basex; x < MAX_SAMPLES; x++) {
1472 		song_sample_t *cur = (current_song->samples + x);
1473 
1474 //              if (!csf_sample_is_empty(current_song->samples + x))
1475 //                      continue;
1476 		if (cur->data != NULL)
1477 			continue;
1478 
1479 		ii->expect_samples++;
1480 		ii->sample_map[slot] = x;
1481 		ii->basex = x + 1;
1482 		return ii->sample_map[slot];
1483 	}
1484 	status_text_flash("Too many samples");
1485 	return 0;
1486 }
1487 
1488