1 /*
2  *  tracker/ModuleEditor.cpp
3  *
4  *  Copyright 2009 Peter Barth
5  *
6  *  This file is part of Milkytracker.
7  *
8  *  Milkytracker is free software: you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation, either version 3 of the License, or
11  *  (at your option) any later version.
12  *
13  *  Milkytracker is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with Milkytracker.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 
23 #include <new>
24 #include "ModuleEditor.h"
25 #include "PatternEditor.h"
26 #include "SampleEditor.h"
27 #include "EnvelopeEditor.h"
28 #include "ModuleServices.h"
29 #include "PlayerCriticalSection.h"
30 #include "TrackerConfig.h"
31 #include "PPSystem.h"
32 
33 static const char validCharacters[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_!.";
34 
35 #ifndef TRUE
36 #define TRUE 1
37 #endif
38 
39 #ifndef FALSE
40 #define FALSE 0
41 #endif
42 
43 // convert string
convertStr(SYSCHAR * buffer,char * src)44 static mp_sint32 convertStr(SYSCHAR* buffer, char* src)
45 {
46 	mp_sint32 j = 0;
47 	for (mp_sint32 i = 0; i < MP_MAXTEXT; i++)
48 	{
49 		if (src[i] == '\0')
50 			break;
51 
52 		bool found = false;
53 		for (mp_sint32 k = 0; k < (signed)(sizeof(validCharacters)/sizeof(char))-1; k++)
54 			if (src[i] == validCharacters[k])
55 			{
56 				found = true;
57 				break;
58 			}
59 
60 		if (found)
61 			buffer[j++] = src[i];
62 	}
63 
64 	buffer[j] = '\0';
65 	return j;
66 }
67 
68 class ChangesListener : public EditorBase::EditorNotificationListener
69 {
70 private:
editorNotification(EditorBase * sender,EditorBase::EditorNotifications notification)71 	virtual void editorNotification(EditorBase* sender, EditorBase::EditorNotifications notification)
72 	{
73 		switch (notification)
74 		{
75 			case EditorBase::NotificationChanges:
76 			{
77 				if (sender == moduleEditor.sampleEditor)
78 					moduleEditor.finishSamples();
79 				moduleEditor.setChanged();
80 				break;
81 			}
82 
83 			case EditorBase::NotificationPrepareCritical:
84 				moduleEditor.enterCriticalSection();
85 				break;
86 
87 			case EditorBase::NotificationUnprepareCritical:
88 				moduleEditor.leaveCriticalSection();
89 				break;
90 			default:
91 				break;
92 		}
93 	}
94 
95 	ModuleEditor& moduleEditor;
96 
97 public:
ChangesListener(ModuleEditor & moduleEditor)98 	ChangesListener(ModuleEditor& moduleEditor) :
99 		moduleEditor(moduleEditor)
100 	{
101 	}
102 };
103 
ModuleEditor()104 ModuleEditor::ModuleEditor() :
105 	module(NULL),
106 	patternEditor(NULL),
107 	sampleEditor(NULL),
108 	envelopeEditor(NULL),
109 	playerCriticalSection(NULL),
110 	changed(false),
111 	eSaveType(ModSaveTypeXM),
112 	lastRequestedPatternIndex(0),
113 	currentOrderIndex(0),
114 	currentPatternIndex(0),
115 	currentInstrumentIndex(0),
116 	currentSampleIndex(0),
117 	enumerationIndex(-1)
118 {
119 	instruments = new TEditorInstrument[MAX_INSTRUMENTS];
120 
121 	moduleFileName = TrackerConfig::untitledSong;
122 
123 	// no extension here
124 	adjustExtension(false);
125 
126 	module = new XModule();
127 
128 	createNewSong();
129 
130 	changesListener = new ChangesListener(*this);
131 
132 	// create pattern editor
133 	patternEditor = new PatternEditor();
134 	patternEditor->addNotificationListener(changesListener);
135 	reloadCurrentPattern();
136 
137 	// create sample editor
138 	sampleEditor = new SampleEditor();
139 	sampleEditor->addNotificationListener(changesListener);
140 	reloadSample(0, 0);
141 
142 	// create envelope editor
143 	envelopeEditor = new EnvelopeEditor();
144 	envelopeEditor->addNotificationListener(changesListener);
145 	envelopeEditor->attachEnvelope(NULL, module);
146 
147 	moduleServices = new ModuleServices(*module);
148 
149 	currentCursorPosition.row = currentCursorPosition.channel = currentCursorPosition.inner = 0;
150 }
151 
~ModuleEditor()152 ModuleEditor::~ModuleEditor()
153 {
154 	delete moduleServices;
155 	delete sampleEditor;
156 	delete patternEditor;
157 	delete envelopeEditor;
158 	// must be deleted AFTER the editors
159 	delete changesListener;
160 	delete module;
161 
162 	delete[] instruments;
163 }
164 
getModuleFileNameFull(ModSaveTypes extension)165 PPSystemString ModuleEditor::getModuleFileNameFull(ModSaveTypes extension/* = ModSaveTypeDefault*/)
166 {
167 	PPSystemString s = moduleFileName;
168 
169 	PPSystemString s2;
170 	if (extension != ModSaveTypeDefault)
171 	{
172 		ModSaveTypes eOldType = eSaveType;
173 		eSaveType = extension;
174 		adjustExtension();
175 		eSaveType = eOldType;
176 	}
177 	s2 = moduleFileName;
178 	moduleFileName = s;
179 	return s2;
180 }
181 
getModuleFileName(ModSaveTypes extension)182 PPSystemString ModuleEditor::getModuleFileName(ModSaveTypes extension/* = ModSaveTypeDefault*/)
183 {
184 	PPSystemString s = getModuleFileNameFull(extension);
185 
186 	return s.stripPath();
187 }
188 
reloadCurrentPattern()189 void ModuleEditor::reloadCurrentPattern()
190 {
191 	TXMPattern* pattern = patternEditor->getPattern();
192 
193 	if (pattern &&
194 		pattern->patternData &&
195 		pattern->channum == TrackerConfig::numPlayerChannels &&
196 		module &&
197 		pattern == &module->phead[getCurrentPatternIndex()])
198 		return;
199 
200 	patternEditor->attachPattern(getPattern(getCurrentPatternIndex()), module);
201 }
202 
reloadSample(mp_sint32 insIndex,mp_sint32 smpIndex)203 void ModuleEditor::reloadSample(mp_sint32 insIndex, mp_sint32 smpIndex)
204 {
205 	sampleEditor->attachSample(getSampleInfo(insIndex, smpIndex), module);
206 }
207 
reloadEnvelope(mp_sint32 insIndex,mp_sint32 smpIndex,mp_sint32 type)208 void ModuleEditor::reloadEnvelope(mp_sint32 insIndex, mp_sint32 smpIndex, mp_sint32 type)
209 {
210 	envelopeEditor->attachEnvelope(getEnvelope(insIndex, smpIndex, type), module);
211 }
212 
enterCriticalSection()213 void ModuleEditor::enterCriticalSection()
214 {
215 	if (playerCriticalSection)
216 		playerCriticalSection->enter();
217 }
218 
leaveCriticalSection()219 void ModuleEditor::leaveCriticalSection()
220 {
221 	if (playerCriticalSection)
222 		playerCriticalSection->leave();
223 }
224 
adjustExtension(bool hasExtension)225 void ModuleEditor::adjustExtension(bool hasExtension/* = true*/)
226 {
227 	if (hasExtension)
228 		moduleFileName = moduleFileName.stripExtension();
229 
230 	switch (eSaveType)
231 	{
232 		case ModSaveTypeXM:
233 			moduleFileName.append(".xm");
234 			break;
235 
236 		case ModSaveTypeMOD:
237 			moduleFileName.append(".mod");
238 			break;
239 
240 		default:
241 			ASSERT(false);
242 	}
243 }
244 
convertInstrument(mp_sint32 i)245 void ModuleEditor::convertInstrument(mp_sint32 i)
246 {
247 	mp_sint32 j,k;
248 
249 	TXMInstrument* ins = &module->instr[i];
250 	instruments[i].instrument = ins;
251 	instruments[i].numUsedSamples = 16;
252 
253 	for (j = 0; j < 16; j++)
254 		instruments[i].usedSamples[j] = i*16+j;
255 
256 	// build FT2 compatible note->sample LUT
257 	for (j = 0; j < MAX_NOTE; j++)
258 	{
259 		mp_sword s = ins->snum[j];
260 
261 		// empty entry
262 		if (s == -1)
263 		{
264 			instruments[i].nbu[j] = /*255*/0;
265 			ins->snum[j] = i*16;
266 			continue;
267 		}
268 
269 		bool found = false;
270 		for (k = 0; k < 16; k++)
271 			if (i*16+k == s)
272 			{
273 				instruments[i].nbu[j] = k;
274 				found = true;
275 				break;
276 			}
277 
278 		if (!found)
279 		{
280 			instruments[i].nbu[j] = /*255*/0;
281 			ins->snum[j] = i*16;
282 			//exit(1);
283 		}
284 	}
285 
286 	if (ins->samp)
287 	{
288 		// take default envelope from first sample in instrument
289 		mp_sint32 venvIndex = module->smp[i*16].venvnum - 1;
290 		if (venvIndex == -1)
291 		{
292 			for (mp_sint32 e = 0; e < module->header.volenvnum; e++)
293 			{
294 				bool used = false;
295 				for (mp_sint32 s = 0; s < module->header.smpnum; s++)
296 				{
297 					if (module->smp[s].venvnum - 1 == e)
298 					{
299 						used = true;
300 						break;
301 					}
302 				}
303 
304 				if (!used)
305 				{
306 					venvIndex = e;
307 					break;
308 				}
309 			}
310 		}
311 
312 		if (venvIndex == -1)
313 		{
314 			TEnvelope venv;
315 			memset(&venv, 0, sizeof(venv));
316 			venv.type = 0;
317 			venv.num = 2;
318 			venv.loops = 0;
319 			venv.loope = 1;
320 			venv.sustain = 0;
321 			venv.env[0][0] = 0;
322 			venv.env[0][1] = 256;
323 			venv.env[1][0] = 32;
324 			venv.env[1][1] = 256;
325 			module->addVolumeEnvelope(venv);
326 			venvIndex = module->numVEnvs - 1;
327 			module->header.volenvnum = module->numVEnvs;
328 		}
329 
330 		instruments[i].volumeEnvelope = venvIndex;
331 
332 		// same for panning envelope index
333 		mp_sint32 penvIndex = module->smp[i*16].penvnum - 1;
334 		if (penvIndex == -1)
335 		{
336 			for (mp_sint32 e = 0; e < module->header.panenvnum; e++)
337 			{
338 				bool used = false;
339 				for (mp_sint32 s = 0; s < module->header.smpnum; s++)
340 				{
341 					if (module->smp[s].penvnum - 1 == e)
342 					{
343 						used = true;
344 						break;
345 					}
346 				}
347 
348 				if (!used)
349 				{
350 					penvIndex = e;
351 					break;
352 				}
353 			}
354 		}
355 
356 		if (penvIndex == -1)
357 		{
358 			TEnvelope penv;
359 			memset(&penv, 0, sizeof(penv));
360 			penv.type=0;
361 			penv.num=2;
362 			penv.loops=0;
363 			penv.loope=1;
364 			penv.sustain = 0;
365 			penv.env[0][0]=0;
366 			penv.env[0][1]=128;
367 			penv.env[1][0]=32;
368 			penv.env[1][1]=128;
369 			module->addPanningEnvelope(penv);
370 			penvIndex = module->numPEnvs - 1;
371 			module->header.panenvnum = module->numPEnvs;
372 		}
373 
374 		instruments[i].panningEnvelope = penvIndex;
375 
376 		mp_sint32 s = instruments[i].usedSamples[0];
377 
378 		// take all fadeout/autovibrato settings from first sample in instrument
379 		instruments[i].volfade = module->smp[s].volfade >> 1;
380 		instruments[i].vibtype = module->smp[s].vibtype;
381 		instruments[i].vibrate = module->smp[s].vibrate;
382 		instruments[i].vibdepth = module->smp[s].vibdepth >> 1;
383 		instruments[i].vibsweep = module->smp[s].vibsweep;
384 	}
385 	else
386 	{
387 
388 		for (j = 0; j < MAX_NOTE; j++)
389 			ins->snum[j] = i*16;
390 
391 		mp_sint32 e;
392 		mp_sint32 venvIndex = - 1;
393 
394 		for (e = 0; e < module->header.volenvnum; e++)
395 		{
396 			bool used = false;
397 			for (mp_sint32 s = 0; s < module->header.smpnum; s++)
398 			{
399 				if (module->smp[s].venvnum - 1 == e)
400 				{
401 					used = true;
402 					break;
403 				}
404 			}
405 
406 			if (!used)
407 			{
408 				venvIndex = e;
409 				break;
410 			}
411 		}
412 
413 		if (venvIndex == -1)
414 		{
415 			TEnvelope venv;
416 			memset(&venv, 0, sizeof(venv));
417 			venv.type=0;
418 			venv.num=2;
419 			venv.loops=0;
420 			venv.loope=1;
421 			venv.sustain = 0;
422 			venv.env[0][0]=0;
423 			venv.env[0][1]=256;
424 			venv.env[1][0]=32;
425 			venv.env[1][1]=256;
426 			module->addVolumeEnvelope(venv);
427 			venvIndex = module->numVEnvs - 1;
428 			module->header.volenvnum = module->numVEnvs;
429 		}
430 
431 		instruments[i].volumeEnvelope = venvIndex;
432 
433 		mp_sint32 penvIndex = - 1;
434 
435 		for (e = 0; e < module->header.panenvnum; e++)
436 		{
437 			bool used = false;
438 			for (mp_sint32 s = 0; s < module->header.smpnum; s++)
439 			{
440 				if (module->smp[s].penvnum - 1 == e)
441 				{
442 					used = true;
443 					break;
444 				}
445 			}
446 
447 			if (!used)
448 			{
449 				penvIndex = e;
450 				break;
451 			}
452 		}
453 
454 		if (penvIndex == -1)
455 		{
456 			TEnvelope penv;
457 			memset(&penv, 0, sizeof(penv));
458 			penv.type=0;
459 			penv.num=2;
460 			penv.loops=0;
461 			penv.loope=1;
462 			penv.sustain = 0;
463 			penv.env[0][0]=0;
464 			penv.env[0][1]=128;
465 			penv.env[1][0]=32;
466 			penv.env[1][1]=128;
467 			module->addPanningEnvelope(penv);
468 			penvIndex = module->numPEnvs - 1;
469 			module->header.panenvnum = module->numPEnvs;
470 		}
471 
472 		instruments[i].panningEnvelope = penvIndex;
473 
474 		//-----------------------------------------------------------
475 		// this will only work if there are 16 sample per instrument
476 		//-----------------------------------------------------------
477 		for (j = 0; j < 16; j++)
478 		{
479 			module->smp[i*16+j].venvnum = venvIndex + 1;
480 			module->smp[i*16+j].penvnum = penvIndex + 1;
481 			// default fade out to cut
482 			module->smp[i*16+j].volfade = 0xFFFF;
483 		}
484 
485 		instruments[i].volfade = 0xFFFF >> 1;
486 		instruments[i].vibtype = 0;
487 		instruments[i].vibrate = 0;
488 		instruments[i].vibdepth = 0;
489 		instruments[i].vibsweep = 0;
490 	}
491 
492 
493 	for (j = 0; j < 16; j++)
494 	{
495 		if (!module->smp[i*16+j].sample)
496 		{
497 			module->smp[i*16+j].vol = 0xFF;
498 			module->smp[i*16+j].pan = 0x80;
499 		}
500 	}
501 }
502 
buildInstrumentTable()503 void ModuleEditor::buildInstrumentTable()
504 {
505 	mp_sint32 i,j;
506 
507 	for (i = 0; i < MAX_INSTRUMENTS; i++)
508 	{
509 		instruments[i].instrument = NULL;
510 		instruments[i].numUsedSamples = 0;
511 		for (j = 0; j < 16; j++)
512 			instruments[i].usedSamples[j] = -1;
513 		instruments[i].volumeEnvelope = instruments[i].panningEnvelope = -1;
514 
515 		memset(instruments[i].nbu, 0, MAX_NOTE);
516 	}
517 
518 	for (i = 0; i < module->header.insnum; i++)
519 	{
520 		convertInstrument(i);
521 	}
522 
523 	validateInstruments();
524 }
525 
validateInstruments()526 void ModuleEditor::validateInstruments()
527 {
528 	for (mp_sint32 i = 0; i < module->header.insnum; i++)
529 	{
530 		mp_sint32 lastUsedInstrument = -1;
531 		for (mp_sint32 j = 15; j >= 0; j--)
532 		{
533 			mp_sint32 s = instruments[i].usedSamples[j];
534 			if (module->smp[s].sample)
535 			{
536 				lastUsedInstrument = j;
537 			}
538 
539 			module->smp[s].flags = 3;
540 		}
541 
542 		instruments[i].instrument->samp = 16;
543 	}
544 }
545 
allocatePattern(TXMPattern * pattern)546 bool ModuleEditor::allocatePattern(TXMPattern* pattern)
547 {
548 	// create empty pattern
549 	pattern->channum = (mp_ubyte)/*numChannels*/TrackerConfig::numPlayerChannels;
550 	pattern->rows = 64;
551 	// create XM style pattern, two effects
552 	pattern->effnum = 2;
553 
554 	mp_sint32 slotSize = pattern->effnum * 2 + 2;
555 
556 	mp_sint32 patternSize = slotSize * pattern->channum * pattern->rows;
557 
558 	pattern->patternData = new mp_ubyte[patternSize];
559 
560 	if (pattern->patternData == NULL)
561 		return false;
562 
563 	memset(pattern->patternData, 0, patternSize);
564 	return true;
565 }
566 
createEmptySong(bool clearPatterns,bool clearInstruments,mp_sint32 numChannels)567 void ModuleEditor::createEmptySong(bool clearPatterns/* = true*/, bool clearInstruments/* = true*/, mp_sint32 numChannels/* = 8*/)
568 {
569 	if (module)
570 	{
571 		enterCriticalSection();
572 
573 		setCurrentOrderIndex(0);
574 		setCurrentPatternIndex(0);
575 
576 		module->createEmptySong(clearPatterns, clearInstruments, numChannels);
577 
578 		if (clearPatterns && clearInstruments)
579 		{
580 			changed = false;
581 
582 			eSaveType = ModSaveTypeXM;
583 
584 			moduleFileName = TrackerConfig::untitledSong;
585 
586 			// no extension
587 			adjustExtension(false);
588 		}
589 		else
590 		{
591 			changed = true;
592 		}
593 
594 		buildInstrumentTable();
595 
596 		lastRequestedPatternIndex = 0;
597 
598 		leaveCriticalSection();
599 	}
600 }
601 
createNewSong(mp_uword numChannels)602 bool ModuleEditor::createNewSong(mp_uword numChannels/*= 8*/)
603 {
604 	module->createEmptySong(true, true, numChannels);
605 
606 	changed = false;
607 
608 	eSaveType = ModSaveTypeXM;
609 
610 	moduleFileName = TrackerConfig::untitledSong;
611 
612 	// no extension
613 	adjustExtension(false);
614 
615 	buildInstrumentTable();
616 
617 	lastRequestedPatternIndex = 0;
618 
619 	return true;
620 }
621 
isEmpty() const622 bool ModuleEditor::isEmpty() const
623 {
624 	mp_sint32 patNum = module->header.patnum;
625 	if (patNum != 1)
626 		return false;
627 
628 	TXMPattern* pattern = &module->phead[0];
629 
630 	if (pattern->patternData != NULL)
631 	{
632 		mp_sint32 slotSize = pattern->effnum * 2 + 2;
633 
634 		mp_sint32 patternSize = slotSize * pattern->channum * pattern->rows;
635 
636 		bool empty = true;
637 		for (mp_sint32 j = 0; j < patternSize; j++)
638 			if (pattern->patternData[j])
639 			{
640 				empty = false;
641 				break;
642 			}
643 
644 		if (!empty)
645 			return false;
646 	}
647 
648 	// step two, find last used instrument
649 	mp_sint32 insNum = module->getNumUsedInstruments();
650 	if (insNum)
651 		return false;
652 
653 	char temp[MAX_TITLETEXT+1];
654 	memset(temp, 0, sizeof(temp));
655 	getTitle(temp, MAX_TITLETEXT);
656 
657 	if (strlen(temp))
658 		return true;
659 
660 	return true;
661 }
662 
openSong(const SYSCHAR * fileName,const SYSCHAR * preferredFileName)663 bool ModuleEditor::openSong(const SYSCHAR* fileName, const SYSCHAR* preferredFileName/* = NULL*/)
664 {
665 	if (!XMFile::exists(fileName))
666 		return false;
667 
668 	mp_sint32 nRes = module->loadModule(fileName);
669 
670 	// unknown format
671 	if (nRes == MP_UNKNOWN_FORMAT)
672 	{
673 		return false;
674 	}
675 
676 	bool res = (nRes == MP_OK);
677 
678 	XModule::ModuleTypes type = XModule::ModuleType_NONE;
679 
680 	if (module->getType() != XModule::ModuleType_XM)
681 	{
682 		type = module->getType();
683 
684 		mp_ubyte oneShotFlags[MAX_INSTRUMENTS];
685 		// save flags for one shot PT style looping, it will be stripped out
686 		// when exporting to XM
687 		if (type == XModule::ModuleType_MOD)
688 		{
689 			memset(oneShotFlags, 0, sizeof(oneShotFlags));
690 			for (mp_sint32 i = 0; i < module->header.insnum; i++)
691 			{
692 				mp_sint32 snum = module->instr[i].snum[0];
693 				if (snum >= 0)
694 				{
695 					oneShotFlags[i] = module->smp[snum].type & 32;
696 				}
697 			}
698 		}
699 
700 		PPSystemString tempFile(getTempFilename());
701 
702 		try
703 		{
704 			res = module->saveExtendedModule(tempFile) == MP_OK;
705 			if(!res)
706 				return res;
707 
708 			res = module->loadModule(tempFile) == MP_OK;
709 		} catch (const std::bad_alloc &) {
710 			return false;
711 		}
712 
713 		// restore one shot looping flag
714 		if (type == XModule::ModuleType_MOD)
715 		{
716 			for (mp_sint32 i = 0; i < module->header.insnum; i++)
717 			{
718 				mp_sint32 snum = module->instr[i].snum[0];
719 				if (snum >= 0)
720 				{
721 					if (oneShotFlags[i])
722 						module->smp[snum].type |= 32;
723 				}
724 			}
725 		}
726 
727 		XMFile::remove(tempFile);
728 	}
729 
730 	if (module->header.channum > TrackerConfig::numPlayerChannels)
731 		res = false;
732 
733 	lastRequestedPatternIndex = 0;
734 
735 	if (res)
736 	{
737 		changed = false;
738 
739 		buildInstrumentTable();
740 
741 		// expand patterns to 32 channels width
742 		for (mp_sint32 i = 0; i < module->header.patnum; i++)
743 			getPattern(i);
744 
745 		PPSystemString strFileName = preferredFileName ? preferredFileName : fileName;
746 
747 		moduleFileName = strFileName.stripExtension();
748 
749 		if (type == XModule::ModuleType_MOD)
750 			eSaveType = ModSaveTypeMOD;
751 		else
752 			eSaveType = ModSaveTypeXM;
753 
754 		// no extension
755 		adjustExtension(false);
756 	}
757 	else
758 	{
759 		createNewSong();
760 	}
761 
762 	cleanUnusedPatterns();
763 
764 	return res;
765 }
766 
saveSong(const SYSCHAR * fileName,ModSaveTypes saveType)767 bool ModuleEditor::saveSong(const SYSCHAR* fileName, ModSaveTypes saveType/* = eXM*/)
768 {
769 	// too risky
770 	//cleanUnusedPatterns();
771 
772 	bool res = false;
773 
774 	switch (saveType)
775 	{
776 		case ModSaveTypeDefault:
777 		case ModSaveTypeXM:
778 			res = module->saveExtendedModule(fileName) == 0;
779 			break;
780 
781 		case ModSaveTypeMOD:
782 			res = module->saveProtrackerModule(fileName) == 0;
783 			break;
784 	}
785 
786 	eSaveType = saveType;
787 
788 	moduleFileName = fileName;
789 
790 	// has extension
791 	adjustExtension();
792 
793 	changed = false;
794 
795 	return res;
796 }
797 
saveBackup(const SYSCHAR * fileName)798 mp_sint32 ModuleEditor::saveBackup(const SYSCHAR* fileName)
799 {
800 	return module->saveExtendedModule(fileName);
801 }
802 
803 
increaseSongLength()804 void ModuleEditor::increaseSongLength()
805 {
806 	if (module->header.ordnum < 255)
807 	{
808 		module->header.ordnum++;
809 		changed = true;
810 	}
811 }
812 
decreaseSongLength()813 void ModuleEditor::decreaseSongLength()
814 {
815 	if (module->header.ordnum > 1)
816 	{
817 		module->header.ordnum--;
818 		changed = true;
819 	}
820 }
821 
increaseRepeatPos()822 void ModuleEditor::increaseRepeatPos()
823 {
824 	mp_uword old = module->header.restart;
825 
826 	if (module->header.restart < 255)
827 		module->header.restart++;
828 
829 	if (module->header.restart >= module->header.ordnum)
830 		module->header.restart = module->header.ordnum - 1;
831 
832 	if (old != module->header.restart)
833 		changed = true;
834 }
835 
decreaseRepeatPos()836 void ModuleEditor::decreaseRepeatPos()
837 {
838 	if (module->header.restart > 0)
839 	{
840 		module->header.restart--;
841 		changed = true;
842 	}
843 }
844 
insertNewOrderPosition(mp_sint32 index)845 bool ModuleEditor::insertNewOrderPosition(mp_sint32 index)
846 {
847 
848 	if (module->header.ordnum >= 255)
849 		return false;
850 
851 	mp_ubyte temp[256];
852 
853 	mp_sint32 i;
854 
855 	for (i = 0; i <= index; i++)
856 		temp[i] = module->header.ord[i];
857 
858 	temp[index+1] = module->header.ord[index];
859 
860 	for (i = index+2; i <= module->header.ordnum; i++)
861 		temp[i] = module->header.ord[i-1];
862 
863 	module->header.ordnum++;
864 
865 	memcpy(module->header.ord, temp, module->header.ordnum);
866 
867 	changed = true;
868 
869 	return true;
870 }
871 
deleteOrderPosition(mp_sint32 index)872 void ModuleEditor::deleteOrderPosition(mp_sint32 index)
873 {
874 	if (index < module->header.ordnum && module->header.ordnum > 1)
875 	{
876 		for (mp_sint32 i = index; i < module->header.ordnum - 1; i++)
877 			module->header.ord[i] = module->header.ord[i+1];
878 
879 		module->header.ordnum--;
880 
881 		changed = true;
882 	}
883 }
884 
seqCurrentOrderPosition(mp_sint32 index,bool clone)885 bool ModuleEditor::seqCurrentOrderPosition(mp_sint32 index, bool clone/* = false*/)
886 {
887 	mp_sint32 i;
888 
889 	if (module->header.ordnum >= 255)
890 		return false;
891 
892 	pp_int32 srcPatternIndex = module->header.ord[index];
893 
894 	mp_sint32 highestPattern = module->header.ord[0];
895 	for (i = 1; i < module->header.ordnum; i++)
896 		if (module->header.ord[i] > highestPattern)
897 			highestPattern = module->header.ord[i];
898 
899 	mp_ubyte temp[256];
900 
901 	for (i = 0; i <= index; i++)
902 		temp[i] = module->header.ord[i];
903 
904 	temp[index+1] = /*module->header.ord[index] + 1*/highestPattern+1;
905 
906 	pp_int32 dstPatternIndex = highestPattern+1;
907 
908 	for (i = index+2; i <= module->header.ordnum; i++)
909 		temp[i] = module->header.ord[i-1];
910 
911 	module->header.ordnum++;
912 
913 	memcpy(module->header.ord, temp, module->header.ordnum);
914 
915 	if (clone)
916 	{
917 		// now clone pattern
918 		module->phead[dstPatternIndex] = module->phead[srcPatternIndex];
919 	}
920 
921 	changed = true;
922 
923 	return true;
924 }
925 
getOrderPosition(mp_sint32 index) const926 mp_sint32 ModuleEditor::getOrderPosition(mp_sint32 index) const
927 {
928 	return module->header.ord[index];
929 }
930 
increaseOrderPosition(mp_sint32 index)931 void ModuleEditor::increaseOrderPosition(mp_sint32 index)
932 {
933 	if (module->header.ord[index] < 255)
934 	{
935 		module->header.ord[index]++;
936 
937 		changed = true;
938 	}
939 }
940 
decreaseOrderPosition(mp_sint32 index)941 void ModuleEditor::decreaseOrderPosition(mp_sint32 index)
942 {
943 	if (module->header.ord[index] > 0)
944 	{
945 		module->header.ord[index]--;
946 
947 		changed = true;
948 	}
949 }
950 
isEditingOrderPosition(mp_sint32 index) const951 bool ModuleEditor::isEditingOrderPosition(mp_sint32 index) const
952 {
953 	if (index < 0 || index >= module->header.ordnum)
954 		return false;
955 
956 	return patternEditor->getPattern() == &module->phead[module->header.ord[index]];
957 }
958 
cleanUnusedPatterns()959 void ModuleEditor::cleanUnusedPatterns()
960 {
961 	if (!module)
962 		return;
963 
964 	for (mp_sint32 i = module->header.patnum - 1; i > lastRequestedPatternIndex; i--)
965 	{
966 		TXMPattern* pattern = &module->phead[i];
967 
968 		if (pattern->patternData == NULL)
969 			continue;
970 
971 		mp_sint32 slotSize = pattern->effnum * 2 + 2;
972 
973 		mp_sint32 patternSize = slotSize * pattern->channum * pattern->rows;
974 
975 		bool empty = true;
976 		for (mp_sint32 j = 0; j < patternSize; j++)
977 			if (pattern->patternData[j])
978 			{
979 				empty = false;
980 				break;
981 			}
982 
983 		if (empty)
984 		{
985 			bool found = false;
986 			for (mp_sint32 j = 0; j < module->header.ordnum; j++)
987 				if (module->header.ord[j] == i)
988 				{
989 					found = true;
990 					break;
991 				}
992 
993 			if (found)
994 				break;
995 
996 			delete[] pattern->patternData;
997 			memset(pattern, 0, sizeof(TXMPattern));
998 			module->header.patnum = i;
999 		}
1000 		else
1001 		{
1002 			break;
1003 		}
1004 	}
1005 }
1006 
1007 ///////////////////////////////////////////////////////////////////////////
1008 // Whenever a pattern is requested we will return a pattern that is
1009 // 32 channels wide, this makes adding/subtracting channels easier
1010 // without losing data in that channel
1011 // When another pattern pattern is selected we will discard unused channels
1012 ///////////////////////////////////////////////////////////////////////////
getPattern(mp_sint32 index,bool cleanUnusedPatterns)1013 TXMPattern* ModuleEditor::getPattern(mp_sint32 index, bool cleanUnusedPatterns/* = true*/)
1014 {
1015 	lastRequestedPatternIndex = index;
1016 
1017 	// handle with care, this might throw away patterns while the player
1018 	// is using them
1019 	if (cleanUnusedPatterns)
1020 		this->cleanUnusedPatterns();
1021 
1022 	// get requested pattern, allocate one if it's empty
1023 	TXMPattern* pattern = &module->phead[index];
1024 
1025 	if (pattern->patternData == NULL)
1026 	{
1027 		bool res = allocatePattern(pattern);
1028 
1029 		if (!res)
1030 			return NULL;
1031 	}
1032 
1033 	// if the number of channels in this pattern is
1034 	// smaller then 32 we resize to 32 channels
1035 	if (pattern->channum < TrackerConfig::numPlayerChannels)
1036 	{
1037 		mp_sint32 slotSize = pattern->effnum * 2 + 2;
1038 
1039 		mp_sint32 patternSize = slotSize * TrackerConfig::numPlayerChannels * pattern->rows;
1040 
1041 		mp_ubyte* newPatternData = new mp_ubyte[patternSize];
1042 
1043 		memset(newPatternData, 0, patternSize);
1044 
1045 		for (mp_sint32 i = 0; i < pattern->rows; i++)
1046 		{
1047 			mp_sint32 srcOffset = i * slotSize * pattern->channum;
1048 			mp_sint32 dstOffset = i * slotSize * TrackerConfig::numPlayerChannels;
1049 			for (mp_sint32 j = 0; j < slotSize * pattern->channum; j++)
1050 				newPatternData[dstOffset++] = pattern->patternData[srcOffset++];
1051 		}
1052 
1053 		delete[] pattern->patternData;
1054 
1055 		pattern->patternData = newPatternData;
1056 
1057 		pattern->channum = (mp_ubyte)TrackerConfig::numPlayerChannels;
1058 	}
1059 
1060 	// update number of patterns in module header if necessary
1061 	if (module->header.patnum < index + 1)
1062 		module->header.patnum = index + 1;
1063 
1064 	return pattern;
1065 
1066 }
1067 
1068 #if 0
1069 mp_sint32 ModuleEditor::allocateSample(mp_sint32 index)
1070 {
1071 	if (index < 0)
1072 		return -1;
1073 
1074 	if (index >= module->header.insnum)
1075 		return -1;
1076 
1077 	// sorry, XM can only handle 16 samples per instrument
1078 	if (instruments[index].numUsedSamples >= 16)
1079 		return -1;
1080 
1081 
1082 	// look if we can find an unused sample
1083 	mp_sint32 s = -1;
1084 
1085 	for (mp_sint32 i = 0; i < module->header.smpnum; i++)
1086 	{
1087 
1088 		bool used = false;
1089 		//if (module->smp[i].sample == NULL && module->smp[i].samplen == 0)
1090 		//{
1091 
1092 			for (mp_sint32 j = 0; j < module->header.insnum; j++)
1093 			{
1094 				for (mp_sint32 k = 0; k < instruments[j].numUsedSamples; k++)
1095 				{
1096 					if (instruments[j].usedSamples[k] == i)
1097 					{
1098 						used = true;
1099 						break;
1100 					}
1101 				}
1102 
1103 				if (used)
1104 					break;
1105 
1106 			}
1107 
1108 		//}
1109 		//else
1110 		//	used = true;
1111 
1112 		if (!used)
1113 		{
1114 			s = i;
1115 			break;
1116 		}
1117 
1118 	}
1119 
1120 	if (s == -1)
1121 	{
1122 		if (module->header.smpnum >= 254)
1123 			return -2;
1124 
1125 		s = module->header.smpnum++;
1126 	}
1127 
1128 	if (module->smp[s].sample)
1129 	{
1130 		module->freeSampleMem((mp_ubyte*)module->smp[s].sample);
1131 		module->smp[s].sample = NULL;
1132 	}
1133 
1134 	if (!instruments[index].numUsedSamples)
1135 	{
1136 		for (mp_sint32 i = 0; i < MAX_NOTE; i++)
1137 		{
1138 			module->instr[index].snum[i] = s;
1139 			instruments[index].nbu[i] = 0;
1140 		}
1141 	}
1142 
1143 	strcpy((char*)module->smp[s].name,"<new sample>");
1144 	module->smp[s].venvnum = instruments[index].volumeEnvelope + 1;
1145 	module->smp[s].penvnum = instruments[index].panningEnvelope + 1;
1146 
1147 	instruments[index].usedSamples[instruments[index].numUsedSamples++] = s;
1148 
1149 	return 0;
1150 
1151 }
1152 #endif
1153 
finishSamples()1154 void ModuleEditor::finishSamples()
1155 {
1156 	module->postProcessSamples();
1157 }
1158 
allocateInstrument()1159 mp_sint32 ModuleEditor::allocateInstrument()
1160 {
1161 	if (module->header.insnum >= 255)
1162 		return -1;
1163 
1164 	enterCriticalSection();
1165 
1166 	mp_sint32 i = module->header.insnum++;
1167 
1168 	module->header.smpnum+=16;
1169 
1170 	convertInstrument(i);
1171 
1172 	validateInstruments();
1173 
1174 	leaveCriticalSection();
1175 
1176 	changed = true;
1177 
1178 	return 0;
1179 }
1180 
1181 // free sample
freeSample(mp_sint32 index)1182 void ModuleEditor::freeSample(mp_sint32 index)
1183 {
1184 	return;
1185 
1186 	if (index < 0)
1187 		return;
1188 
1189 	if (index >= module->header.insnum)
1190 		return;
1191 
1192 	if (instruments[index].numUsedSamples)
1193 	{
1194 		instruments[index].usedSamples[--instruments[index].numUsedSamples] = -1;
1195 
1196 		mp_sint32 i;
1197 
1198 		mp_ubyte* nbu = instruments[index].nbu;
1199 
1200 		for (i = 0; i < MAX_NOTE; i++)
1201 			if (nbu[i] == instruments[index].numUsedSamples)
1202 				nbu[i] = 255;
1203 
1204  		for (i = 0; i < MAX_NOTE; i++)
1205 		{
1206 			if (nbu[i] != 255)
1207 				module->instr[index].snum[i] = instruments[index].usedSamples[nbu[i]];
1208 			else
1209 				module->instr[index].snum[i] = 255;
1210 		}
1211 
1212 	}
1213 
1214 }
1215 
clearSample(mp_sint32 smpIndex)1216 void ModuleEditor::clearSample(mp_sint32 smpIndex)
1217 {
1218 	if (smpIndex >= 0 && smpIndex < MP_MAXSAMPLES)
1219 	{
1220 		TXMSample* dst = &module->smp[smpIndex];
1221 
1222 		module->freeSampleMem((mp_ubyte*)dst->sample);
1223 		dst->sample = NULL;
1224 		dst->samplen = 0;
1225 		dst->loopstart = 0;
1226 		dst->looplen = 0;
1227 
1228 		changed = true;
1229 	}
1230 }
1231 
clearSample(mp_sint32 insIndex,mp_sint32 smpIndex)1232 void ModuleEditor::clearSample(mp_sint32 insIndex, mp_sint32 smpIndex)
1233 {
1234 	if (insIndex < module->header.insnum && smpIndex < 16)
1235 	{
1236 		mp_sint32 s = instruments[insIndex].usedSamples[smpIndex];
1237 
1238 		clearSample(s);
1239 	}
1240 }
1241 
loadSample(const SYSCHAR * fileName,mp_sint32 insIndex,mp_sint32 smpIndex,mp_sint32 channelIndex,const SYSCHAR * preferredFileName)1242 bool ModuleEditor::loadSample(const SYSCHAR* fileName,
1243 							  mp_sint32 insIndex,
1244 							  mp_sint32 smpIndex,
1245 							  mp_sint32 channelIndex,
1246 							  const SYSCHAR* preferredFileName/* = NULL*/)
1247 {
1248 	PPSystemString sysPreferredName(preferredFileName ? preferredFileName : fileName);
1249 	sysPreferredName = sysPreferredName.stripPath();
1250 	char* preferredNameASCIIZ = sysPreferredName.toASCIIZ();
1251 	PPString preferredName(preferredNameASCIIZ);
1252 	delete[] preferredNameASCIIZ;
1253 
1254 	SampleLoaderGeneric sampleLoader(fileName, *module);
1255 	sampleLoader.setPreferredDefaultName(preferredName);
1256 
1257 	if (insIndex < module->header.insnum && smpIndex < 16)
1258 	{
1259 		enterCriticalSection();
1260 
1261 		bool res = sampleLoader.loadSample(instruments[insIndex].usedSamples[smpIndex], channelIndex) == 0;
1262 
1263 		if (res)
1264 		{
1265 			TXMSample* dst = &module->smp[instruments[insIndex].usedSamples[smpIndex]];
1266 
1267 			ASSERT(dst);
1268 
1269 			// default values first
1270 			dst->flags = 3;
1271 			dst->venvnum = instruments[insIndex].volumeEnvelope+1;
1272 			dst->penvnum = instruments[insIndex].panningEnvelope+1;
1273 			dst->fenvnum = dst->vibenvnum = 0;
1274 
1275 			dst->vibtype = instruments[insIndex].vibtype;
1276 			dst->vibsweep = instruments[insIndex].vibsweep;
1277 			dst->vibdepth = instruments[insIndex].vibdepth << 1;
1278 			dst->vibrate = instruments[insIndex].vibrate;
1279 			dst->volfade = instruments[insIndex].volfade << 1;
1280 
1281 			finishSamples();
1282 
1283 			validateInstruments();
1284 
1285 			changed = true;
1286 		}
1287 
1288 		leaveCriticalSection();
1289 
1290 		return res;
1291 	}
1292 
1293 	return false;
1294 }
1295 
getNumSampleChannels(const SYSCHAR * fileName)1296 mp_sint32 ModuleEditor::getNumSampleChannels(const SYSCHAR* fileName)
1297 {
1298 	SampleLoaderGeneric sampleLoader(fileName, *module);
1299 	return sampleLoader.getNumChannels();
1300 }
1301 
1302 // get name of channel in sample as returned by sample loader
getNameOfSampleChannel(const SYSCHAR * fileName,mp_sint32 index)1303 const char* ModuleEditor::getNameOfSampleChannel(const SYSCHAR* fileName, mp_sint32 index)
1304 {
1305 	SampleLoaderGeneric sampleLoader(fileName, *module);
1306 	return sampleLoader.getChannelName(index);
1307 }
1308 
saveSample(const SYSCHAR * fileName,mp_sint32 insIndex,mp_sint32 smpIndex,SampleFormatTypes format)1309 bool ModuleEditor::saveSample(const SYSCHAR* fileName, mp_sint32 insIndex, mp_sint32 smpIndex, SampleFormatTypes format)
1310 {
1311 	SampleLoaderGeneric sampleLoader(fileName, *module);
1312 
1313 	if (insIndex < module->header.insnum && smpIndex < 16)
1314 	{
1315 		bool res = false;
1316 
1317 		switch (format)
1318 		{
1319 			case SampleFormatTypeWAV:
1320 				res = sampleLoader.saveSample(fileName, instruments[insIndex].usedSamples[smpIndex], SampleLoaderGeneric::OutputFiletypeWAV) == 0;
1321 				break;
1322 			case SampleFormatTypeIFF:
1323 				res = sampleLoader.saveSample(fileName, instruments[insIndex].usedSamples[smpIndex], SampleLoaderGeneric::OutputFiletypeIFF) == 0;
1324 				break;
1325 		}
1326 
1327 		return res;
1328 	}
1329 
1330 	return false;
1331 }
1332 
getSampleFileName(mp_sint32 insIndex,mp_sint32 smpIndex)1333 const PPSystemString& ModuleEditor::getSampleFileName(mp_sint32 insIndex, mp_sint32 smpIndex)
1334 {
1335 	SYSCHAR buffer[MP_MAXTEXT+1];
1336 	memset(buffer, 0, sizeof(buffer));
1337 
1338 	TXMSample* smp = getSampleInfo(insIndex,smpIndex);
1339 
1340 	mp_sint32 len = convertStr(buffer, smp->name);
1341 
1342 	if (!len)
1343 		sampleFileName = getInstrumentFileName(insIndex);
1344 	else
1345 	{
1346 		sampleFileName = buffer;
1347 		sampleFileName = sampleFileName.stripExtension();
1348 	}
1349 
1350 	return sampleFileName;
1351 }
1352 
1353 // free last instrument
freeInstrument()1354 void ModuleEditor::freeInstrument()
1355 {
1356 	if (module->header.insnum <= 1)
1357 		return;
1358 
1359 	enterCriticalSection();
1360 
1361 	for (mp_sint32 j = 0; j < 16; j++)
1362 		instruments[module->header.insnum].usedSamples[j] = -1;
1363 
1364 	instruments[module->header.insnum].volumeEnvelope = -1;
1365 	instruments[module->header.insnum].panningEnvelope = -1;
1366 
1367 	memset(instruments[module->header.insnum].nbu, 0, MAX_NOTE);
1368 
1369 	module->header.insnum--;
1370 
1371 	module->header.smpnum-=16;
1372 
1373 	leaveCriticalSection();
1374 
1375 	changed = true;
1376 }
1377 
insertXIInstrument(mp_sint32 index,const XIInstrument * ins)1378 bool ModuleEditor::insertXIInstrument(mp_sint32 index, const XIInstrument* ins)
1379 {
1380 	ASSERT(index < module->header.insnum);
1381 
1382 	mp_sint32 j;
1383 
1384 	ASSERT(instruments[index].numUsedSamples == 16);
1385 
1386 	memcpy(instruments[index].nbu, ins->nbu, MAX_NOTE);
1387 
1388 	for (j = 0; j < MAX_NOTE; j++)
1389 		instruments[index].instrument->snum[j] = index*16 + ins->nbu[j];
1390 
1391 	memcpy(instruments[index].instrument->name, ins->name, MAX_INSTEXT);
1392 
1393 	instruments[index].instrument->samp = ins->numsamples;
1394 
1395 	memcpy(&module->venvs[instruments[index].volumeEnvelope], &ins->venv, sizeof(ins->venv));
1396 	memcpy(&module->penvs[instruments[index].panningEnvelope], &ins->penv, sizeof(ins->penv));
1397 
1398 	instruments[index].volfade = ins->volfade>>1;
1399 	instruments[index].vibtype = ins->vibtype;
1400 	instruments[index].vibrate = ins->vibrate;
1401 	instruments[index].vibdepth = ins->vibdepth>>1;
1402 	instruments[index].vibsweep = ins->vibsweep;
1403 
1404 	// Wipe samples first
1405 	for (j = 0; j < 16; j++)
1406 	{
1407 		mp_sint32 s = instruments[index].usedSamples[j];
1408 
1409 		TXMSample* smp = &module->smp[s];
1410 
1411 		if (smp->sample)
1412 		{
1413 			module->freeSampleMem((mp_ubyte*)smp->sample);
1414 			smp->sample = NULL;
1415 		}
1416 
1417 		smp->vol = 255;
1418 		smp->pan = 0x80;
1419 		smp->finetune = 0;
1420 		smp->relnote = 0;
1421 		smp->looplen = smp->loopstart = smp->samplen = 0;
1422 		smp->flags = smp->type = 0;
1423 		memset(smp->name, 0, sizeof(smp->name));
1424 	}
1425 
1426 
1427 	for (j = 0; j < ins->numsamples; j++)
1428 	{
1429 		mp_sint32 s = instruments[index].usedSamples[j];
1430 
1431 		// 16 bit samples
1432 		if (ins->samples[j].samplen && ins->samples[j].sample)
1433 		{
1434 			if (ins->samples[j].type & 16)
1435 			{
1436 				module->smp[s].sample = (mp_sbyte*)module->allocSampleMem(ins->samples[j].samplen*2);
1437 				if (module->smp[s].sample == NULL)
1438 					return false;
1439 
1440 				TXMSample::copyPaddedMem(module->smp[s].sample, ins->samples[j].sample, ins->samples[j].samplen*2);
1441 			}
1442 			else
1443 			{
1444 				module->smp[s].sample = (mp_sbyte*)module->allocSampleMem(ins->samples[j].samplen);
1445 				if (module->smp[s].sample == NULL)
1446 					return false;
1447 
1448 				TXMSample::copyPaddedMem(module->smp[s].sample, ins->samples[j].sample, ins->samples[j].samplen);
1449 			}
1450 		}
1451 
1452 		const TXMSample* src = &ins->samples[j];
1453 		TXMSample* dst = &module->smp[s];
1454 
1455 		// default values first
1456 		dst->flags = 3;
1457 		dst->venvnum = instruments[index].volumeEnvelope+1;
1458 		dst->penvnum = instruments[index].panningEnvelope+1;
1459 		dst->fenvnum = dst->vibenvnum = 0;
1460 
1461 		// copy from original instrument
1462 		dst->samplen = src->samplen;
1463 		dst->loopstart = src->loopstart;
1464 		dst->looplen = src->looplen;
1465 		dst->vol = src->vol;
1466 		dst->finetune = src->finetune;
1467 		dst->type = src->type;
1468 		dst->pan = src->pan;
1469 		dst->relnote = src->relnote;
1470 
1471 		dst->vibtype = src->vibtype;
1472 		dst->vibsweep = src->vibsweep;
1473 		dst->vibdepth = src->vibdepth;
1474 		dst->vibrate = src->vibrate;
1475 		dst->volfade = src->volfade;
1476 
1477 		memcpy(dst->name, src->name, sizeof(dst->name));
1478 	}
1479 
1480 	changed = true;
1481 
1482 	return true;
1483 }
1484 
extractXIInstrument(mp_sint32 index)1485 XIInstrument* ModuleEditor::extractXIInstrument(mp_sint32 index)
1486 {
1487 	ASSERT(index < module->header.insnum);
1488 
1489 	XIInstrument* ins = new XIInstrument();
1490 
1491 	if (ins == NULL)
1492 		return NULL;
1493 
1494 	mp_sint32 j;
1495 
1496 	ASSERT(instruments[index].numUsedSamples == 16);
1497 
1498 	memcpy(ins->nbu, instruments[index].nbu, MAX_NOTE);
1499 
1500 	memcpy(ins->name, instruments[index].instrument->name, MAX_INSTEXT);
1501 
1502 	ins->numsamples = 16;
1503 
1504 	memcpy(&ins->venv, &module->venvs[instruments[index].volumeEnvelope], sizeof(ins->venv));
1505 	memcpy(&ins->penv, &module->penvs[instruments[index].panningEnvelope], sizeof(ins->penv));
1506 
1507 	ins->volfade = instruments[index].volfade<<1;
1508 	ins->vibtype = instruments[index].vibtype;
1509 	ins->vibrate = instruments[index].vibrate;
1510 	ins->vibdepth = instruments[index].vibdepth<<1;
1511 	ins->vibsweep = instruments[index].vibsweep;
1512 
1513 	for (j = 0; j < ins->numsamples; j++)
1514 	{
1515 		mp_sint32 s = instruments[index].usedSamples[j];
1516 
1517 		TXMSample* dst = &ins->samples[j];
1518 		TXMSample* src = &module->smp[s];
1519 
1520 		// default values first
1521 		dst->flags = 3;
1522 		dst->venvnum = instruments[index].volumeEnvelope+1;
1523 		dst->penvnum = instruments[index].panningEnvelope+1;
1524 		dst->fenvnum = dst->vibenvnum = 0;
1525 
1526 		// copy from original instrument
1527 		dst->samplen = src->samplen;
1528 		dst->loopstart = src->loopstart;
1529 		dst->looplen = src->looplen;
1530 		dst->vol = src->vol;
1531 		dst->finetune = src->finetune;
1532 		dst->type = src->type;
1533 		dst->pan = src->pan;
1534 		dst->relnote = src->relnote;
1535 		dst->sample = src->sample;
1536 
1537 		dst->vibtype = src->vibtype;
1538 		dst->vibsweep = src->vibsweep;
1539 		dst->vibdepth = src->vibdepth;
1540 		dst->vibrate = src->vibrate;
1541 		dst->volfade = src->volfade;
1542 
1543 		memcpy(dst->name, src->name, sizeof(dst->name));
1544 	}
1545 
1546 	return ins;
1547 }
1548 
loadInstrument(const SYSCHAR * fileName,mp_sint32 index)1549 bool ModuleEditor::loadInstrument(const SYSCHAR* fileName, mp_sint32 index)
1550 {
1551 	ASSERT(index < module->header.insnum);
1552 
1553 	XIInstrument* ins = new XIInstrument();
1554 
1555 	bool res = ins->load(fileName) == 0;
1556 
1557 	if (res)
1558 	{
1559 		res = insertXIInstrument(index, ins);
1560 
1561 		finishSamples();
1562 
1563 		validateInstruments();
1564 	}
1565 
1566 	delete ins;
1567 
1568 	return res;
1569 }
1570 
saveInstrument(const SYSCHAR * fileName,mp_sint32 index)1571 bool ModuleEditor::saveInstrument(const SYSCHAR* fileName, mp_sint32 index)
1572 {
1573 	ASSERT(index < module->header.insnum);
1574 
1575 	XIInstrument* ins = extractXIInstrument(index);
1576 
1577 	bool res = true;
1578 
1579 	if (ins)
1580 	{
1581 		ins->save(fileName);
1582 	}
1583 
1584 	return res;
1585 }
1586 
zapInstrument(mp_sint32 index)1587 bool ModuleEditor::zapInstrument(mp_sint32 index)
1588 {
1589 	ASSERT(index < module->header.insnum);
1590 
1591 	enterCriticalSection();
1592 
1593 	XIInstrument ins;
1594 
1595 	bool res = insertXIInstrument(index, &ins);
1596 
1597 	finishSamples();
1598 
1599 	validateInstruments();
1600 
1601 	leaveCriticalSection();
1602 
1603 	changed = true;
1604 
1605 	return res;
1606 }
1607 
getInstrumentFileName(mp_sint32 index)1608 const PPSystemString& ModuleEditor::getInstrumentFileName(mp_sint32 index)
1609 {
1610 	SYSCHAR buffer[MP_MAXTEXT+1];
1611 	memset(buffer, 0, sizeof(buffer));
1612 
1613 	TEditorInstrument* ins = getInstrumentInfo(index);
1614 
1615 	mp_sint32 len = convertStr(buffer, ins->instrument->name);
1616 
1617 	if (!len)
1618 		instrumentFileName = "Untitled";
1619 	else
1620 	{
1621 		instrumentFileName = buffer;
1622 		instrumentFileName = instrumentFileName.stripExtension();
1623 	}
1624 
1625 	return instrumentFileName;
1626 }
1627 
copyInstrument(ModuleEditor & dstModule,mp_sint32 dstIndex,ModuleEditor & srcModule,mp_sint32 srcIndex)1628 bool ModuleEditor::copyInstrument(ModuleEditor& dstModule, mp_sint32 dstIndex,
1629 								  ModuleEditor& srcModule, mp_sint32 srcIndex)
1630 {
1631 	ASSERT(srcIndex < srcModule.module->header.insnum);
1632 	ASSERT(dstIndex < dstModule.module->header.insnum);
1633 
1634 	XIInstrument* srcIns = srcModule.extractXIInstrument(srcIndex);
1635 
1636 	if (!srcIns)
1637 		return false;
1638 
1639 	XIInstrument* dstIns = new XIInstrument(*srcIns);
1640 
1641 	if (!dstIns)
1642 	{
1643 		delete srcIns;
1644 		return false;
1645 	}
1646 
1647 	dstModule.enterCriticalSection();
1648 
1649 	bool res = dstModule.insertXIInstrument(dstIndex, dstIns);
1650 
1651 	if (res)
1652 	{
1653 		dstModule.finishSamples();
1654 		dstModule.validateInstruments();
1655 	}
1656 
1657 	delete dstIns;
1658 	delete srcIns;
1659 
1660 	dstModule.leaveCriticalSection();
1661 
1662 	return res;
1663 }
1664 
swapInstruments(ModuleEditor & dstModule,mp_sint32 dstIndex,ModuleEditor & srcModule,mp_sint32 srcIndex)1665 bool ModuleEditor::swapInstruments(ModuleEditor& dstModule, mp_sint32 dstIndex,
1666 								   ModuleEditor& srcModule, mp_sint32 srcIndex)
1667 {
1668 	ASSERT(srcIndex < srcModule.module->header.insnum);
1669 	ASSERT(dstIndex < dstModule.module->header.insnum);
1670 
1671 	XIInstrument* srcIns = srcModule.extractXIInstrument(srcIndex);
1672 
1673 	if (!srcIns)
1674 		return false;
1675 
1676 	XIInstrument* dstIns = dstModule.extractXIInstrument(dstIndex);
1677 
1678 	if (!dstIns)
1679 	{
1680 		delete srcIns;
1681 		return false;
1682 	}
1683 
1684 	XIInstrument* swapSrc = new XIInstrument(*srcIns);
1685 
1686 	if (!swapSrc)
1687 	{
1688 		delete dstIns;
1689 		delete srcIns;
1690 		return false;
1691 	}
1692 
1693 	XIInstrument* swapDst = new XIInstrument(*dstIns);
1694 
1695 	if (!swapDst)
1696 	{
1697 		delete swapSrc;
1698 		delete dstIns;
1699 		delete srcIns;
1700 		return false;
1701 	}
1702 
1703 	delete dstIns;
1704 	delete srcIns;
1705 
1706 	if (&dstModule == &srcModule)
1707 	{
1708 		dstModule.enterCriticalSection();
1709 	}
1710 	else
1711 	{
1712 		srcModule.enterCriticalSection();
1713 		dstModule.enterCriticalSection();
1714 	}
1715 
1716 	bool res = dstModule.insertXIInstrument(dstIndex, swapSrc);
1717 	res = srcModule.insertXIInstrument(srcIndex, swapDst) && res;
1718 
1719 	if (res)
1720 	{
1721 		srcModule.finishSamples();
1722 		srcModule.validateInstruments();
1723 
1724 		dstModule.finishSamples();
1725 		dstModule.validateInstruments();
1726 	}
1727 
1728 	delete swapDst;
1729 	delete swapSrc;
1730 
1731 	if (&dstModule == &srcModule)
1732 	{
1733 		dstModule.leaveCriticalSection();
1734 	}
1735 	else
1736 	{
1737 		dstModule.leaveCriticalSection();
1738 		srcModule.leaveCriticalSection();
1739 	}
1740 
1741 	return res;
1742 }
1743 
copySample(ModuleEditor & dstModule,mp_sint32 dstInsIndex,mp_sint32 dstIndex,ModuleEditor & srcModule,mp_sint32 srcInsIndex,mp_sint32 srcIndex)1744 bool ModuleEditor::copySample(ModuleEditor& dstModule, mp_sint32 dstInsIndex, mp_sint32 dstIndex,
1745 							  ModuleEditor& srcModule, mp_sint32 srcInsIndex, mp_sint32 srcIndex)
1746 {
1747 	ASSERT(srcInsIndex < srcModule.module->header.insnum);
1748 	ASSERT(dstInsIndex < dstModule.module->header.insnum);
1749 
1750 	ASSERT(srcIndex < 16);
1751 	ASSERT(dstIndex < 16);
1752 
1753 	bool res = true;
1754 
1755 	TXMSample* dstSmp = dstModule.getSampleInfo(dstInsIndex, dstIndex);
1756 	TXMSample* srcSmp = srcModule.getSampleInfo(srcInsIndex, srcIndex);
1757 
1758 	dstModule.enterCriticalSection();
1759 
1760 	if (dstSmp->sample && dstSmp->samplen)
1761 		dstModule.module->freeSampleMem((mp_ubyte*)dstSmp->sample);
1762 
1763 	// assign attributes
1764 	*dstSmp = *srcSmp;
1765 
1766 	mp_sint32 sampleSize = (srcSmp->samplen * ((srcSmp->type & 16) ? 16:8)) >> 3;
1767 	if (sampleSize && srcSmp->sample)
1768 	{
1769 		dstSmp->sample = (mp_sbyte*)dstModule.module->allocSampleMem(sampleSize);
1770 		if (dstSmp->sample)
1771 		{
1772 			TXMSample::copyPaddedMem(dstSmp->sample, srcSmp->sample, sampleSize);
1773 			dstModule.finishSamples();
1774 			dstModule.validateInstruments();
1775 		}
1776 		else res = false;
1777 	}
1778 
1779 	dstModule.leaveCriticalSection();
1780 
1781 	return res;
1782 }
1783 
swapSamples(ModuleEditor & dstModule,mp_sint32 dstInsIndex,mp_sint32 dstIndex,ModuleEditor & srcModule,mp_sint32 srcInsIndex,mp_sint32 srcIndex)1784 bool ModuleEditor::swapSamples(ModuleEditor& dstModule, mp_sint32 dstInsIndex, mp_sint32 dstIndex,
1785 							   ModuleEditor& srcModule, mp_sint32 srcInsIndex, mp_sint32 srcIndex)
1786 {
1787 	ASSERT(srcInsIndex < srcModule.module->header.insnum);
1788 	ASSERT(dstInsIndex < dstModule.module->header.insnum);
1789 
1790 	ASSERT(srcIndex < 16);
1791 	ASSERT(dstIndex < 16);
1792 
1793 	bool res = true;
1794 
1795 	if (&dstModule == &srcModule)
1796 	{
1797 		dstModule.enterCriticalSection();
1798 	}
1799 	else
1800 	{
1801 		srcModule.enterCriticalSection();
1802 		dstModule.enterCriticalSection();
1803 	}
1804 
1805 	TXMSample* dstSmp = dstModule.getSampleInfo(dstInsIndex, dstIndex);
1806 	TXMSample* srcSmp = srcModule.getSampleInfo(srcInsIndex, srcIndex);
1807 
1808 	TXMSample tmpSmp;
1809 
1810 	srcModule.module->removeSamplePtr((mp_ubyte*)srcSmp->sample);
1811 	dstModule.module->removeSamplePtr((mp_ubyte*)dstSmp->sample);
1812 
1813 	tmpSmp = *dstSmp;
1814 	*dstSmp = *srcSmp;
1815 	*srcSmp = tmpSmp;
1816 
1817 	srcModule.module->insertSamplePtr((mp_ubyte*)srcSmp->sample);
1818 	dstModule.module->insertSamplePtr((mp_ubyte*)dstSmp->sample);
1819 
1820 	if (&dstModule == &srcModule)
1821 	{
1822 		dstModule.leaveCriticalSection();
1823 	}
1824 	else
1825 	{
1826 		dstModule.leaveCriticalSection();
1827 		srcModule.leaveCriticalSection();
1828 	}
1829 
1830 	return res;
1831 }
1832 
setNumChannels(mp_uint32 channels)1833 void ModuleEditor::setNumChannels(mp_uint32 channels)
1834 {
1835 	if (module->header.channum != channels)
1836 		changed = true;
1837 	module->header.channum = channels;
1838 }
1839 
setTitle(const char * name,mp_uint32 length)1840 void ModuleEditor::setTitle(const char* name, mp_uint32 length)
1841 {
1842 	insertText(module->header.name, name, length);
1843 	changed = true;
1844 }
1845 
getTitle(char * name,mp_uint32 length) const1846 void ModuleEditor::getTitle(char* name, mp_uint32 length) const
1847 {
1848 	if (length > MAX_TITLETEXT)
1849 		length = MAX_TITLETEXT;
1850 	XModule::convertStr(name, (char*)module->header.name, length, false);
1851 }
1852 
setNumOrders(mp_sint32 numOrders)1853 void ModuleEditor::setNumOrders(mp_sint32 numOrders)
1854 {
1855 	if (numOrders > 255)
1856 		numOrders = 255;
1857 	if (numOrders < 1)
1858 		numOrders = 1;
1859 
1860 	if (module->header.ordnum != numOrders)
1861 		changed = true;
1862 
1863 	module->header.ordnum = numOrders;
1864 }
1865 
setFrequency(Frequencies frequency)1866 void ModuleEditor::setFrequency(Frequencies frequency)
1867 {
1868 	// changes are made using the settings panel
1869 	// do not flag changes here
1870 	//mp_sint32 old = module->header.freqtab;
1871 	module->header.freqtab &= ~1;
1872 	module->header.freqtab |= frequency;
1873 	//if (old != module->header.freqtab)
1874 	//	changed = true;
1875 }
1876 
setSampleName(mp_sint32 insIndex,mp_sint32 smpIndex,const char * name,mp_uint32 length)1877 void ModuleEditor::setSampleName(mp_sint32 insIndex, mp_sint32 smpIndex, const char* name, mp_uint32 length)
1878 {
1879 	insertText((char*)getSampleInfo(insIndex, smpIndex)->name, name, length);
1880 	changed = true;
1881 }
1882 
getSampleName(mp_sint32 insIndex,mp_sint32 smpIndex,char * name,mp_uint32 length) const1883 void ModuleEditor::getSampleName(mp_sint32 insIndex, mp_sint32 smpIndex, char* name, mp_uint32 length) const
1884 {
1885 	if (length > MAX_SMPTEXT)
1886 		length = MAX_SMPTEXT;
1887 	XModule::convertStr(name, (char*)getSampleInfoInternal(insIndex, smpIndex)->name, length, false);
1888 }
1889 
setCurrentSampleName(const char * name,mp_uint32 length)1890 void ModuleEditor::setCurrentSampleName(const char* name, mp_uint32 length)
1891 {
1892 	if (sampleEditor->getSample() == NULL)
1893 		return;
1894 
1895 	insertText((char*)sampleEditor->getSample()->name, name, length);
1896 	changed = true;
1897 }
1898 
getFirstSampleInfo()1899 TXMSample* ModuleEditor::getFirstSampleInfo()
1900 {
1901 	enumerationIndex = 0;
1902 	if (enumerationIndex < module->header.smpnum)
1903 		return &module->smp[enumerationIndex];
1904 	else
1905 		return NULL;
1906 }
1907 
getNextSampleInfo()1908 TXMSample* ModuleEditor::getNextSampleInfo()
1909 {
1910 	enumerationIndex++;
1911 	if (enumerationIndex >= module->header.smpnum)
1912 	{
1913 		enumerationIndex = -1;
1914 		return NULL;
1915 	}
1916 
1917 	return &module->smp[enumerationIndex];
1918 }
1919 
setInstrumentName(mp_sint32 insIndex,const char * name,mp_uint32 length)1920 void ModuleEditor::setInstrumentName(mp_sint32 insIndex, const char* name, mp_uint32 length)
1921 {
1922 	insertText(module->instr[insIndex].name, name, length);
1923 	changed = true;
1924 }
1925 
getInstrumentName(mp_sint32 insIndex,char * name,mp_uint32 length) const1926 void ModuleEditor::getInstrumentName(mp_sint32 insIndex, char* name, mp_uint32 length) const
1927 {
1928 	if (length > MAX_INSTEXT)
1929 		length = MAX_INSTEXT;
1930 
1931 	XModule::convertStr(name, module->instr[insIndex].name, length, false);
1932 }
1933 
getEnvelope(mp_sint32 insIndex,mp_sint32 smpIndex,mp_sint32 type)1934 TEnvelope* ModuleEditor::getEnvelope(mp_sint32 insIndex, mp_sint32 smpIndex, mp_sint32 type)
1935 {
1936 	if (insIndex < 0 || insIndex >= module->header.insnum)
1937 		return NULL;
1938 
1939 	if (smpIndex < 0 || smpIndex >= instruments[insIndex].numUsedSamples)
1940 		return NULL;
1941 
1942 	TXMSample* smp = getSampleInfo(insIndex,smpIndex);
1943 
1944 	// no envelopes available, assign some
1945 	if (smp->venvnum == 0)
1946 		smp->venvnum = instruments[insIndex].volumeEnvelope+1;
1947 	// no envelope available, assign one
1948 	if (smp->penvnum == 0)
1949 		smp->penvnum = instruments[insIndex].panningEnvelope+1;
1950 
1951 	if (type == 0 && smp->venvnum)
1952 	{
1953 		return &module->venvs[smp->venvnum-1];
1954 	}
1955 	else if (type == 1 && smp->penvnum)
1956 	{
1957 		return &module->penvs[smp->penvnum-1];
1958 	}
1959 
1960 	return NULL;
1961 }
1962 
getSampleTable(mp_sint32 insIndex)1963 const mp_ubyte* ModuleEditor::getSampleTable(mp_sint32 insIndex)
1964 {
1965 	if (insIndex < 0 || insIndex >= module->header.insnum)
1966 		return NULL;
1967 
1968 	return instruments[insIndex].nbu;
1969 }
1970 
updateSampleTable(mp_sint32 index,const mp_ubyte * nbu)1971 void ModuleEditor::updateSampleTable(mp_sint32 index, const mp_ubyte* nbu)
1972 {
1973 	if (nbu == NULL)
1974 		return;
1975 
1976 	if (index < 0 || index >= module->header.insnum)
1977 		return;
1978 
1979 	// cope with FT2 noterange (= 96)
1980 	memcpy(instruments[index].nbu, nbu, MAX_NOTE);
1981 
1982 	// update module data
1983 	for (mp_sint32 i = 0; i < MAX_NOTE; i++)
1984 	{
1985 		if (nbu[i] != 255)
1986 			module->instr[index].snum[i] = instruments[index].usedSamples[nbu[i]];
1987 		else
1988 			module->instr[index].snum[i] = 255;
1989 
1990 	}
1991 
1992 	changed = true;
1993 }
1994 
updateInstrumentData(mp_sint32 index)1995 void ModuleEditor::updateInstrumentData(mp_sint32 index)
1996 {
1997 
1998 	if (index < 0)
1999 		return;
2000 
2001 	if (index >= module->header.insnum)
2002 		return;
2003 
2004 	for (mp_sint32 i = 0; i < instruments[index].numUsedSamples; i++)
2005 	{
2006 		mp_sint32 s = instruments[index].usedSamples[i];
2007 
2008 		TXMSample* smp = &module->smp[s];
2009 
2010 		smp->volfade = instruments[index].volfade << 1;
2011 		if (smp->volfade == 65534) smp->volfade++;
2012 		smp->vibtype = instruments[index].vibtype;
2013 		smp->vibrate = instruments[index].vibrate;
2014 		smp->vibdepth = instruments[index].vibdepth << 1;
2015 		smp->vibsweep = instruments[index].vibsweep;
2016 	}
2017 
2018 	changed = true;
2019 
2020 }
2021 
insRemapSong(pp_int32 oldIns,pp_int32 newIns)2022 pp_int32 ModuleEditor::insRemapSong(pp_int32 oldIns, pp_int32 newIns)
2023 {
2024 	mp_sint32 resCnt = 0;
2025 
2026 	PatternEditorTools patternEditorTools;
2027 
2028 	for (mp_sint32 k = 0; k < module->header.patnum; k++)
2029 	{
2030 		patternEditorTools.attachPattern(&module->phead[k]);
2031 		resCnt+=patternEditorTools.insRemap(oldIns, newIns);
2032 	}
2033 
2034 	if (resCnt)
2035 		changed = true;
2036 
2037 	return resCnt;
2038 }
2039 
noteTransposeSong(const PatternEditorTools::TransposeParameters & transposeParameters,bool evaluate)2040 pp_int32 ModuleEditor::noteTransposeSong(const PatternEditorTools::TransposeParameters& transposeParameters, bool evaluate/* = false*/)
2041 {
2042 	mp_sint32 resCnt = 0;
2043 	pp_int32 fuckupCnt = 0;
2044 
2045 	PatternEditorTools patternEditorTools;
2046 
2047 	for (mp_sint32 k = 0; k < module->header.patnum; k++)
2048 	{
2049 		patternEditorTools.attachPattern(&module->phead[k]);
2050 
2051 		if (evaluate)
2052 			fuckupCnt+=patternEditorTools.noteTranspose(transposeParameters, evaluate);
2053 		else
2054 			resCnt+=patternEditorTools.noteTranspose(transposeParameters, evaluate);
2055 	}
2056 
2057 	if (!evaluate)
2058 	{
2059 		if (resCnt)
2060 			changed = true;
2061 
2062 		return resCnt;
2063 	}
2064 	else
2065 		return fuckupCnt;
2066 }
2067 
panConvertSong(PanConversionTypes type)2068 pp_int32 ModuleEditor::panConvertSong(PanConversionTypes type)
2069 {
2070 	mp_sint32 resCnt = 0;
2071 
2072 	for (mp_sint32 k = 0; k < module->header.patnum; k++)
2073 	{
2074 		TXMPattern* pattern = &module->phead[k];
2075 
2076 		if (pattern->patternData == NULL)
2077 			continue;
2078 
2079 		mp_sint32 slotSize = pattern->effnum * 2 + 2;
2080 		mp_sint32 rowSizeSrc = slotSize*pattern->channum;
2081 
2082 		for (pp_int32 i = 0; i < pattern->rows; i++)
2083 			for (pp_int32 j = 0; j < pattern->channum; j++)
2084 			{
2085 				mp_ubyte* src = pattern->patternData + i*rowSizeSrc+j*slotSize;
2086 
2087 				switch (type)
2088 				{
2089 					case PanConversionTypeConvert_E8x:
2090 						if (src[4] == 0x38)
2091 						{
2092 							src[4] = 0x08;
2093 							src[5] = (mp_ubyte)XModule::pan15to255(src[5]);
2094 							resCnt++;
2095 						}
2096 						break;
2097 					case PanConversionTypeConvert_80x:
2098 						if (src[4] == 0x08)
2099 						{
2100 							src[5] = (mp_ubyte)XModule::pan15to255(src[5]);
2101 							resCnt++;
2102 						}
2103 						break;
2104 					case PanConversionTypeRemove_E8x:
2105 						if (src[4] == 0x38)
2106 						{
2107 							src[4] = src[5] = 0x0;
2108 							resCnt++;
2109 						}
2110 						break;
2111 					case PanConversionTypeRemove_8xx:
2112 						if (src[4] == 0x08)
2113 						{
2114 							src[4] = src[5] = 0x0;
2115 							resCnt++;
2116 						}
2117 						break;
2118 				}
2119 			}
2120 
2121 	}
2122 
2123 	if (resCnt)
2124 		changed = true;
2125 
2126 	return resCnt;
2127 }
2128 
removeUnusedPatterns(bool evaluate)2129 pp_int32 ModuleEditor::removeUnusedPatterns(bool evaluate)
2130 {
2131 	mp_sint32 result = module->removeUnusedPatterns(evaluate);
2132 
2133 	if (!evaluate && result)
2134 	{
2135 		changed = true;
2136 		if (currentPatternIndex > module->header.patnum - 1)
2137 			currentPatternIndex = module->header.patnum - 1;
2138 	}
2139 	return result;
2140 }
2141 
removeUnusedInstruments(bool evaluate,bool remap)2142 pp_int32 ModuleEditor::removeUnusedInstruments(bool evaluate, bool remap)
2143 {
2144 	mp_sint32 i,j,k;
2145 
2146 	mp_ubyte* bitMap = new mp_ubyte[MAX_INSTRUMENTS];
2147 
2148 	memset(bitMap, 0, sizeof(mp_ubyte)*MAX_INSTRUMENTS);
2149 
2150 	for (k = 0; k < module->header.patnum; k++)
2151 	{
2152 		TXMPattern* pattern = &module->phead[k];
2153 
2154 		if (pattern->patternData == NULL)
2155 			continue;
2156 
2157 		mp_sint32 slotSize = pattern->effnum * 2 + 2;
2158 		mp_sint32 rowSizeSrc = slotSize*pattern->channum;
2159 
2160 		for (i = 0; i < pattern->rows; i++)
2161 			for (j = 0; j < pattern->channum; j++)
2162 			{
2163 				mp_ubyte* src = pattern->patternData + i*rowSizeSrc+j*slotSize;
2164 
2165 				if (src[1])
2166 				{
2167 					bitMap[src[1]-1] = TRUE;
2168 				}
2169 			}
2170 
2171 	}
2172 
2173 	mp_sint32 result = 0;
2174 	for (i = 0; i < module->header.insnum; i++)
2175 	{
2176 		if (!bitMap[i])
2177 		{
2178 			result++;
2179 			if (!evaluate)
2180 				zapInstrument(i);
2181 		}
2182 	}
2183 
2184 	if (!evaluate)
2185 	{
2186 		mp_sint32* insRelocTable = new mp_sint32[MAX_INSTRUMENTS];
2187 
2188 		for (i = 0, j = 0; i < module->header.insnum; i++)
2189 		{
2190 			if (bitMap[i])
2191 			{
2192 				insRelocTable[i] = j++;
2193 			}
2194 		}
2195 
2196 		for (i = 0, k = 0; i < module->header.insnum; i++)
2197 		{
2198 			if (bitMap[i])
2199 			{
2200 				j = insRelocTable[i];
2201 
2202 				if (j < i)
2203 				{
2204 					XIInstrument* ins = extractXIInstrument(i);
2205 
2206 					insertXIInstrument(j, ins);
2207 
2208 					delete ins;
2209 
2210 					insRemapSong(i+1, j+1);
2211 
2212 					zapInstrument(i);
2213 
2214 				}
2215 				k++;
2216 			}
2217 		}
2218 		delete[] insRelocTable;
2219 
2220 		// zero number of instruments is not allowed
2221 		if (k == 0)
2222 		{
2223 			result--;
2224 			k++;
2225 		}
2226 
2227 		module->header.insnum = k;
2228 		module->header.smpnum = k*16;
2229 	}
2230 	else
2231 	{
2232 		if (module->header.insnum - result <= 0)
2233 			result--;
2234 	}
2235 
2236 	if (!evaluate && result)
2237 		changed = true;
2238 
2239 	delete[] bitMap;
2240 
2241 	return result;
2242 }
2243 
removeUnusedSamples(bool evaluate)2244 pp_int32 ModuleEditor::removeUnusedSamples(bool evaluate)
2245 {
2246 	mp_sint32 i,j,k;
2247 
2248 	mp_ubyte* bitMap = new mp_ubyte[MP_MAXSAMPLES];
2249 
2250 	memset(bitMap, 0, sizeof(mp_ubyte)*MP_MAXSAMPLES);
2251 
2252 	mp_ubyte* lastIns = new mp_ubyte[module->header.channum];
2253 	memset(lastIns, 0, module->header.channum);
2254 
2255 	for (mp_sint32 l = 0; l < module->header.ordnum; l++)
2256 	{
2257 		k = module->header.ord[l];
2258 
2259 		TXMPattern* pattern = &module->phead[k];
2260 
2261 		if (pattern->patternData == NULL)
2262 			continue;
2263 
2264 		mp_sint32 slotSize = pattern->effnum * 2 + 2;
2265 		mp_sint32 rowSizeSrc = slotSize*pattern->channum;
2266 
2267 		for (i = 0; i < pattern->rows; i++)
2268 			for (j = 0; j < pattern->channum; j++)
2269 			{
2270 				mp_ubyte* src = pattern->patternData + i*rowSizeSrc+j*slotSize;
2271 
2272 				if (src[1])
2273 				{
2274 					lastIns[j] = src[1];
2275 #if 0
2276 					// just assume, that if an instrument is used
2277 					// in the pattern, that the first sample of this instrument
2278 					// is kept even if there isn't any note played with that instrument
2279 					mp_sint32 insIndex = lastIns[j] - 1;
2280 					mp_sint32 smpIndex = module->instr[insIndex].snum[0];
2281 					if (smpIndex >= 0 && smpIndex < MP_MAXSAMPLES)
2282 						bitMap[smpIndex] = TRUE;
2283 #endif
2284 				}
2285 
2286 				if (src[0] && src[0] < 120)
2287 				{
2288 					if (lastIns[j])
2289 					{
2290 						mp_sint32 insIndex = lastIns[j] - 1;
2291 
2292 						mp_sint32 smpIndex = module->instr[insIndex].snum[src[0]-1];
2293 
2294 						if (smpIndex >= 0 && smpIndex < MP_MAXSAMPLES)
2295 							bitMap[smpIndex] = TRUE;
2296 					}
2297 				}
2298 			}
2299 
2300 	}
2301 
2302 	delete[] lastIns;
2303 
2304 	mp_sint32 result = 0;
2305 	for (i = 0; i < module->header.smpnum; i++)
2306 	{
2307 		if (!bitMap[i] && module->smp[i].sample)
2308 		{
2309 			result++;
2310 			if (!evaluate)
2311 			{
2312 				clearSample(i);
2313 				// wipe out sample slot
2314 				memset(module->smp + i, 0, sizeof(TXMSample));
2315 			}
2316 		}
2317 	}
2318 
2319 	// relocate samples
2320 	if (!evaluate)
2321 	{
2322 		for (i = 0; i < module->header.insnum; i++)
2323 		{
2324 			mp_sint32 smpRelocTable[16];
2325 			for (j = 0; j < 16; j++)
2326 				smpRelocTable[j] = -1;
2327 
2328 			mp_sint32 s = 0;
2329 			TXMSample* src = module->smp + 16*i;
2330 			TXMSample* dst = src;
2331 			for (j = 0; j < 16; j++, src++)
2332 			{
2333 				k = i*16+j;
2334 				if (bitMap[k])
2335 				{
2336 					if (src != dst)
2337 					{
2338 						*dst = *src;
2339 						// wipe out source sample
2340 						memset(src, 0, sizeof(TXMSample));
2341 					}
2342 					smpRelocTable[j] = s++;
2343 					dst++;
2344 				}
2345 			}
2346 
2347 			// adjust the FT2 style sample->note mapping table
2348 			TEditorInstrument* ins = instruments + i;
2349 
2350 			for (j = 0; j < MAX_NOTE; j++)
2351 				if (ins->nbu[j] < 16 && smpRelocTable[ins->nbu[j]] != -1)
2352 					ins->nbu[j] = smpRelocTable[ins->nbu[j]];
2353 				else
2354 					ins->nbu[j] = 0;
2355 
2356 			// convert back to milkytracker module style mapping
2357 			for (j = 0; j < MAX_NOTE; j++)
2358 				module->instr[i].snum[j] = i * 16 + ins->nbu[j];
2359 
2360 		}
2361 	}
2362 
2363 	if (!evaluate && result)
2364 		changed = true;
2365 
2366 	delete[] bitMap;
2367 
2368 	return result;
2369 }
2370 
relocateCommands(const PatternEditorTools::RelocateParameters & relocateParameters,bool evaluate)2371 pp_int32 ModuleEditor::relocateCommands(const PatternEditorTools::RelocateParameters& relocateParameters, bool evaluate)
2372 {
2373 	mp_sint32 result = 0;
2374 
2375 	PatternEditorTools patternEditorTools;
2376 
2377 	for (mp_sint32 k = 0; k < module->header.patnum; k++)
2378 	{
2379 		patternEditorTools.attachPattern(&module->phead[k]);
2380 		result+=patternEditorTools.relocateCommands(relocateParameters, evaluate);
2381 	}
2382 
2383 	if (!evaluate && result)
2384 		changed = true;
2385 
2386 	return result;
2387 }
2388 
zeroOperands(const PatternEditorTools::OperandOptimizeParameters & optimizeParameters,bool evaluate)2389 pp_int32 ModuleEditor::zeroOperands(const PatternEditorTools::OperandOptimizeParameters& optimizeParameters, bool evaluate)
2390 {
2391 	mp_sint32 result = 0;
2392 
2393 	PatternEditorTools patternEditorTools;
2394 
2395 	for (mp_sint32 k = 0; k < module->header.patnum; k++)
2396 	{
2397 		patternEditorTools.attachPattern(&module->phead[k]);
2398 		result+=patternEditorTools.zeroOperands(optimizeParameters, evaluate);
2399 	}
2400 
2401 	if (!evaluate && result)
2402 		changed = true;
2403 
2404 	return result;
2405 }
2406 
fillOperands(const PatternEditorTools::OperandOptimizeParameters & optimizeParameters,bool evaluate)2407 pp_int32 ModuleEditor::fillOperands(const PatternEditorTools::OperandOptimizeParameters& optimizeParameters, bool evaluate)
2408 {
2409 	mp_sint32 result = 0;
2410 
2411 	PatternEditorTools patternEditorTools;
2412 
2413 	for (mp_sint32 k = 0; k < module->header.patnum; k++)
2414 	{
2415 		patternEditorTools.attachPattern(&module->phead[k]);
2416 		result+=patternEditorTools.fillOperands(optimizeParameters, evaluate);
2417 	}
2418 
2419 	if (!evaluate && result)
2420 		changed = true;
2421 
2422 	return result;
2423 }
2424 
optimizeSamples(bool convertTo8Bit,bool minimize,mp_sint32 & numConvertedSamples,mp_sint32 & numMinimizedSamples,bool evaluate)2425 void ModuleEditor::optimizeSamples(bool convertTo8Bit, bool minimize,
2426 								   mp_sint32& numConvertedSamples, mp_sint32& numMinimizedSamples,
2427 								   bool evaluate)
2428 {
2429 	TXMSample* oldSmp = sampleEditor->getSample();
2430 
2431 	TXMSample* smp = getFirstSampleInfo();
2432 
2433 	sampleEditor->activateUndoStack(false);
2434 
2435 	numConvertedSamples = numMinimizedSamples = 0;
2436 
2437 	while (smp)
2438 	{
2439 		sampleEditor->attachSample(smp, module);
2440 
2441 		// check for 16 bit sample
2442 		if ((smp->type & 16) && smp->sample && smp->samplen && convertTo8Bit)
2443 		{
2444 			if (!evaluate)
2445 				sampleEditor->convertSampleResolution(true);
2446 			numConvertedSamples++;
2447 		}
2448 		if (smp->sample && smp->samplen && smp->isMinimizable() && minimize)
2449 		{
2450 			if (!evaluate)
2451 				sampleEditor->minimizeSample();
2452 			numMinimizedSamples++;
2453 		}
2454 
2455 		smp = getNextSampleInfo();
2456 	}
2457 
2458 	sampleEditor->activateUndoStack(true);
2459 
2460 	sampleEditor->attachSample(oldSmp, module);
2461 
2462 	if (!evaluate && (numMinimizedSamples || numConvertedSamples))
2463 		changed = true;
2464 }
2465 
insertText(char * dst,const char * src,mp_sint32 max)2466 void ModuleEditor::insertText(char* dst, const char* src, mp_sint32 max)
2467 {
2468 	char name[MP_MAXTEXT+1];
2469 
2470 	ASSERT((signed)sizeof(name) >= max && strlen(src) <= sizeof(name));
2471 
2472 	memset(name, 0, sizeof(name));
2473 	memcpy(name, src, (signed)strlen(src) <= max ? strlen(src) : max);
2474 	memcpy(dst, name, max);
2475 }
2476 
getTempFilename()2477 PPSystemString ModuleEditor::getTempFilename()
2478 {
2479 	return PPSystemString(System::getTempFileName());
2480 }
2481 
2482