shithub: ft²

Download patch

ref: 22a8376772b6e264828cbde7d478483288fa867d
parent: 4afaa08eef7e43682284d15be646538293cee1ae
author: Olav Sørensen <olav.sorensen@live.no>
date: Tue Dec 24 14:30:14 EST 2024

Fix some edge-cases for Oxy and Gxy in the .IT loader

--- a/src/modloaders/ft2_load_it.c
+++ b/src/modloaders/ft2_load_it.c
@@ -152,6 +152,7 @@
 	bool oldFormat = (itHdr.cmwt < 0x200);
 	bool songUsesInstruments = !!(itHdr.flags & 4);
 	bool oldEffects = !!(itHdr.flags & 16);
+	bool compatGxx = !!(itHdr.flags & 32);
 
 	// read order list
 	for (int32_t i = 0; i < MAX_ORDERS; i++)
@@ -664,10 +665,14 @@
 	songTmp.numChannels = MIN((numChannels + 1) & ~1, MAX_CHANNELS);
 
 	// convert pattern data
-	
+
+	uint8_t lastInstr[MAX_CHANNELS], lastGInstr[MAX_CHANNELS];
 	uint8_t lastDxy[MAX_CHANNELS], lastExy[MAX_CHANNELS], lastFxy[MAX_CHANNELS];
 	uint8_t lastJxy[MAX_CHANNELS], lastKxy[MAX_CHANNELS], lastLxy[MAX_CHANNELS];
+	uint8_t lastOxx[MAX_CHANNELS];
 
+	memset(lastInstr, 0, sizeof (lastInstr));
+	memset(lastGInstr, 0, sizeof (lastGInstr));
 	memset(lastDxy, 0, sizeof (lastDxy));
 	memset(lastExy, 0, sizeof (lastExy));
 	memset(lastFxy, 0, sizeof (lastFxy));
@@ -674,6 +679,7 @@
 	memset(lastJxy, 0, sizeof (lastJxy));
 	memset(lastKxy, 0, sizeof (lastKxy));
 	memset(lastLxy, 0, sizeof (lastLxy));
+	memset(lastOxx, 0, sizeof (lastOxx));
 
 	for (int32_t i = 0; i < songTmp.pattNum; i++)
 	{
@@ -685,6 +691,9 @@
 		{
 			for (int32_t ch = 0; ch < songTmp.numChannels; ch++, p++)
 			{
+				if (p->instr > 0)
+					lastInstr[ch] = p->instr;
+
 				// effect
 				if (p->efx != 0)
 				{
@@ -803,8 +812,16 @@
 						}
 						break;
 
-						case 'G': p->efx = 3; break; // tone portamento
+						case 'G': // tone portamento
+						{
+							p->efx = 3;
 
+							// remove illegal slides (this is not quite right, but good enough)
+							if (!compatGxx && p->instr != 0 && p->instr != lastGInstr[ch])
+								p->efx = p->efxData = 0;
+						}
+						break;
+
 						case 'H': // vibrato
 						{
 							p->efx = 4;
@@ -912,8 +929,47 @@
 						}
 						break;
 
-						case 'O': p->efx = 0x9; break; // set sample offset
+						case 'O': // set sample offset
+						{
+							p->efx = 0x9;
 
+							if (p->efxData > 0)
+								lastOxx[ch] = p->efxData;
+
+							// handle cases where the sample offset is after the end of the sample
+							if (lastInstr[ch] > 0 && lastOxx[ch] > 0 && p->note > 0 && p->note <= 96)
+							{
+								instr_t *ins = instrTmp[lastInstr[ch]];
+								if (ins != NULL)
+								{
+									const uint8_t sample = ins->note2SampleLUT[p->note-1];
+									if (sample < MAX_SMP_PER_INST)
+									{
+										sample_t *s = &ins->smp[sample];
+										if (s->length > 0)
+										{
+											const bool loopEnabled = (GET_LOOPTYPE(s->flags) != LOOP_DISABLED);
+											const uint32_t sampleEnd = loopEnabled ? s->loopStart+s->loopLength : s->length;
+
+											if (lastOxx[ch]*256UL >= sampleEnd)
+											{
+												if (oldEffects)
+												{
+													if (loopEnabled)
+														p->efxData = (uint8_t)(sampleEnd >> 8);
+												}
+												else
+												{
+													p->efx = p->efxData = 0;
+												}
+											}
+										}
+									}
+								}
+							}
+						}
+						break;
+
 						case 'P': // panning slide
 						{
 							p->efx = 16 + ('P' - 'G');
@@ -1043,6 +1099,9 @@
 				{
 					p->efxData = 0;
 				}
+
+				if (p->instr != 0 && p->efx != 0x3)
+					lastGInstr[ch] = p->instr;
 
 				// volume column
 				if (p->vol > 0)
--