Skip to content

Commit 22a8376

Browse files
committed
Fix some edge-cases for Oxy and Gxy in the .IT loader
1 parent 4afaa08 commit 22a8376

File tree

1 file changed

+62
-3
lines changed

1 file changed

+62
-3
lines changed

Diff for: src/modloaders/ft2_load_it.c

+62-3
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ bool loadIT(FILE *f, uint32_t filesize)
152152
bool oldFormat = (itHdr.cmwt < 0x200);
153153
bool songUsesInstruments = !!(itHdr.flags & 4);
154154
bool oldEffects = !!(itHdr.flags & 16);
155+
bool compatGxx = !!(itHdr.flags & 32);
155156

156157
// read order list
157158
for (int32_t i = 0; i < MAX_ORDERS; i++)
@@ -664,16 +665,21 @@ bool loadIT(FILE *f, uint32_t filesize)
664665
songTmp.numChannels = MIN((numChannels + 1) & ~1, MAX_CHANNELS);
665666

666667
// convert pattern data
667-
668+
669+
uint8_t lastInstr[MAX_CHANNELS], lastGInstr[MAX_CHANNELS];
668670
uint8_t lastDxy[MAX_CHANNELS], lastExy[MAX_CHANNELS], lastFxy[MAX_CHANNELS];
669671
uint8_t lastJxy[MAX_CHANNELS], lastKxy[MAX_CHANNELS], lastLxy[MAX_CHANNELS];
672+
uint8_t lastOxx[MAX_CHANNELS];
670673

674+
memset(lastInstr, 0, sizeof (lastInstr));
675+
memset(lastGInstr, 0, sizeof (lastGInstr));
671676
memset(lastDxy, 0, sizeof (lastDxy));
672677
memset(lastExy, 0, sizeof (lastExy));
673678
memset(lastFxy, 0, sizeof (lastFxy));
674679
memset(lastJxy, 0, sizeof (lastJxy));
675680
memset(lastKxy, 0, sizeof (lastKxy));
676681
memset(lastLxy, 0, sizeof (lastLxy));
682+
memset(lastOxx, 0, sizeof (lastOxx));
677683

678684
for (int32_t i = 0; i < songTmp.pattNum; i++)
679685
{
@@ -685,6 +691,9 @@ bool loadIT(FILE *f, uint32_t filesize)
685691
{
686692
for (int32_t ch = 0; ch < songTmp.numChannels; ch++, p++)
687693
{
694+
if (p->instr > 0)
695+
lastInstr[ch] = p->instr;
696+
688697
// effect
689698
if (p->efx != 0)
690699
{
@@ -803,7 +812,15 @@ bool loadIT(FILE *f, uint32_t filesize)
803812
}
804813
break;
805814

806-
case 'G': p->efx = 3; break; // tone portamento
815+
case 'G': // tone portamento
816+
{
817+
p->efx = 3;
818+
819+
// remove illegal slides (this is not quite right, but good enough)
820+
if (!compatGxx && p->instr != 0 && p->instr != lastGInstr[ch])
821+
p->efx = p->efxData = 0;
822+
}
823+
break;
807824

808825
case 'H': // vibrato
809826
{
@@ -912,7 +929,46 @@ bool loadIT(FILE *f, uint32_t filesize)
912929
}
913930
break;
914931

915-
case 'O': p->efx = 0x9; break; // set sample offset
932+
case 'O': // set sample offset
933+
{
934+
p->efx = 0x9;
935+
936+
if (p->efxData > 0)
937+
lastOxx[ch] = p->efxData;
938+
939+
// handle cases where the sample offset is after the end of the sample
940+
if (lastInstr[ch] > 0 && lastOxx[ch] > 0 && p->note > 0 && p->note <= 96)
941+
{
942+
instr_t *ins = instrTmp[lastInstr[ch]];
943+
if (ins != NULL)
944+
{
945+
const uint8_t sample = ins->note2SampleLUT[p->note-1];
946+
if (sample < MAX_SMP_PER_INST)
947+
{
948+
sample_t *s = &ins->smp[sample];
949+
if (s->length > 0)
950+
{
951+
const bool loopEnabled = (GET_LOOPTYPE(s->flags) != LOOP_DISABLED);
952+
const uint32_t sampleEnd = loopEnabled ? s->loopStart+s->loopLength : s->length;
953+
954+
if (lastOxx[ch]*256UL >= sampleEnd)
955+
{
956+
if (oldEffects)
957+
{
958+
if (loopEnabled)
959+
p->efxData = (uint8_t)(sampleEnd >> 8);
960+
}
961+
else
962+
{
963+
p->efx = p->efxData = 0;
964+
}
965+
}
966+
}
967+
}
968+
}
969+
}
970+
}
971+
break;
916972

917973
case 'P': // panning slide
918974
{
@@ -1044,6 +1100,9 @@ bool loadIT(FILE *f, uint32_t filesize)
10441100
p->efxData = 0;
10451101
}
10461102

1103+
if (p->instr != 0 && p->efx != 0x3)
1104+
lastGInstr[ch] = p->instr;
1105+
10471106
// volume column
10481107
if (p->vol > 0)
10491108
{

0 commit comments

Comments
 (0)